diff --git a/Cargo.lock b/Cargo.lock index 40a39393..1aa007ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -153,9 +153,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e614738943d3f68c628ae3dbce7c3daffb196665f82f8c8ea6b65de73c79429" +checksum = "998282f8f49ccd6116b0ed8a4de0fbd3151697920e7c7533416d6e25e76434a7" dependencies = [ "futures-core", "memchr", @@ -679,18 +679,18 @@ dependencies = [ [[package]] name = "derive_builder" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd33f37ee6a119146a1781d3356a7c26028f83d779b2e04ecd45fdc75c76877b" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ "derive_builder_macro", ] [[package]] name = "derive_builder_core" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7431fa049613920234f22c47fdc33e6cf3ee83067091ea4277a3f8c4587aae38" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ "darling", "proc-macro2", @@ -700,9 +700,9 @@ dependencies = [ [[package]] name = "derive_builder_macro" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4abae7035bf79b9877b779505d8cf3749285b80c43941eda66604841889451dc" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", "syn", @@ -868,6 +868,7 @@ dependencies = [ "img-parts", "indexmap", "jieba-rs", + "jiff", "latex2mathml", "mozjpeg", "nanoid", @@ -1387,6 +1388,12 @@ dependencies = [ "regex", ] +[[package]] +name = "jiff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a45489186a6123c128fdf6016183fcfab7113e1820eb813127e036e287233fb" + [[package]] name = "jobserver" version = "0.1.32" @@ -1398,9 +1405,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "0cb94a0ffd3f3ee755c20f7d8752f45cac88605a4dcf808abcff72873296ec7b" dependencies = [ "wasm-bindgen", ] @@ -3156,9 +3163,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "ef073ced962d62984fb38a36e5fdc1a2b23c9e0e1fa0689bb97afa4202ef6887" dependencies = [ "cfg-if", "once_cell", @@ -3167,9 +3174,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "c4bfab14ef75323f4eb75fa52ee0a3fb59611977fd3240da19b2cf36ff85030e" dependencies = [ "bumpalo", "log", @@ -3182,9 +3189,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "65471f79c1022ffa5291d33520cbbb53b7687b01c2f8e83b57d102eed7ed479d" dependencies = [ "cfg-if", "js-sys", @@ -3194,9 +3201,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "a7bec9830f60924d9ceb3ef99d55c155be8afa76954edffbb5936ff4509474e7" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3204,9 +3211,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "4c74f6e152a76a2ad448e223b0fc0b6b5747649c3d769cc6bf45737bf97d0ed6" dependencies = [ "proc-macro2", "quote", @@ -3217,15 +3224,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "a42f6c679374623f295a8623adfe63d9284091245c3504bde47c17a3ce2777d9" [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "44188d185b5bdcae1052d08bcbcf9091a5524038d4572cc4f4f2bb9d5554ddd9" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index 7b27f084..230c9808 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ image = { version = "0.25.2", default-features = false, features = ["jpeg", "png img-parts = "0.3.0" indexmap = "2" jieba-rs = "0.7.0" +jiff = { version = "0.1.13", default-features = false, features = ["std"] } latex2mathml = "0.2.3" mozjpeg = "0.10.10" nanoid = "0.4.0" diff --git a/src/controller/db_utils.rs b/src/controller/db_utils.rs index 37ae6c8d..4cb66f32 100644 --- a/src/controller/db_utils.rs +++ b/src/controller/db_utils.rs @@ -1,7 +1,7 @@ use super::meta_handler::ParamsPage; use crate::error::AppError; use bincode::{config::standard, Decode, Encode}; -use chrono::Utc; +use jiff::Timestamp; use nanoid::nanoid; use sled::{Db, IVec, Iter, Tree}; use std::iter::Rev; @@ -18,7 +18,7 @@ pub async fn clear_invalid(db: &Db, tree_name: &str) -> Result<(), AppError> { .split_once('_') .and_then(|s| i64::from_str_radix(s.0, 16).ok()); if let Some(time_stamp) = time_stamp { - if time_stamp < Utc::now().timestamp() { + if time_stamp < Timestamp::now().as_second() { tree.remove(k)?; } } @@ -382,7 +382,7 @@ pub(super) fn get_id_by_name( /// ``` pub(super) fn generate_nanoid_ttl(seconds: i64) -> String { let nanoid = nanoid!(); - let exp = Utc::now().timestamp() + seconds; + let exp = Timestamp::now().as_second() + seconds; format!("{exp:x}_{nanoid}") } diff --git a/src/controller/feed.rs b/src/controller/feed.rs index 595f10bc..3cb4cae4 100644 --- a/src/controller/feed.rs +++ b/src/controller/feed.rs @@ -25,8 +25,8 @@ use axum_extra::{ TypedHeader, }; use cached::proc_macro::cached; -use chrono::{DateTime, Utc}; use garde::Validate; +use jiff::Timestamp; use reqwest::Client; use serde::Deserialize; use sled::Db; @@ -48,13 +48,13 @@ impl TryFrom for SourceItem { type Error = AppError; fn try_from(rss: rss::Item) -> Result { let updated = if let Some(ref pub_date) = rss.pub_date { - if let Ok(ts) = DateTime::parse_from_rfc2822(pub_date) { - ts.timestamp() + if let Ok(ts) = pub_date.parse::() { + ts.as_second() } else { - Utc::now().timestamp() + Timestamp::now().as_second() } } else { - Utc::now().timestamp() + Timestamp::now().as_second() }; let Some(link) = rss.link else { @@ -791,7 +791,7 @@ pub(crate) async fn feed_star( if star_tree.contains_key(&k)? { star_tree.remove(&k)?; } else { - let now = Utc::now().timestamp(); + let now = Timestamp::now().as_second(); star_tree.insert(&k, i64_to_ivec(now))?; } } diff --git a/src/controller/fmt.rs b/src/controller/fmt.rs index 0e3f8c13..cf3f4a43 100644 --- a/src/controller/fmt.rs +++ b/src/controller/fmt.rs @@ -1,14 +1,14 @@ use std::sync::LazyLock; -use chrono::DateTime; +use jiff::Timestamp; use pulldown_cmark::{html, CodeBlockKind, Event, Options, Tag}; use syntect::{highlighting::ThemeSet, html::highlighted_html_for_string, parsing::SyntaxSet}; /// convert a `i64` timestamp to a date [`String`] pub(super) fn ts_to_date(timestamp: i64) -> String { - DateTime::from_timestamp(timestamp, 0) + Timestamp::from_second(timestamp) .unwrap() - .format("%Y-%m-%d") + .strftime("%Y-%m-%d") .to_string() } diff --git a/src/controller/inn.rs b/src/controller/inn.rs index 576f905d..121427ac 100644 --- a/src/controller/inn.rs +++ b/src/controller/inn.rs @@ -43,6 +43,7 @@ use bincode::config::standard; use cached::proc_macro::cached; use chrono::{DateTime, Utc}; use garde::Validate; +use jiff::Timestamp; use serde::Deserialize; use sled::{transaction::ConflictableTransactionError, Transactional}; use sled::{Batch, Db}; @@ -308,7 +309,7 @@ pub(crate) async fn mod_inn_post( topics, inn_type: inn_type as u8, early_birds: input.early_birds, - created_at: Utc::now().timestamp(), + created_at: Timestamp::now().as_second(), limit_edit_seconds: input.limit_edit_seconds, }; @@ -579,7 +580,7 @@ pub(crate) async fn edit_post( let mut post: Post = get_one(&DB, "posts", pid)?; let inn: Inn = get_one(&DB, "inns", post.iid)?; - if (post.created_at + (inn.limit_edit_seconds as i64) < Utc::now().timestamp()) + if (post.created_at + (inn.limit_edit_seconds as i64) < Timestamp::now().as_second()) && inn.limit_edit_seconds != 0 { return Err(AppError::Unauthorized); @@ -691,7 +692,7 @@ pub(crate) async fn edit_post_post( return Err(AppError::Unauthorized); } - let mut created_at = Utc::now().timestamp(); + let mut created_at = Timestamp::now().as_second(); if created_at - claim.last_write < site_config.post_interval { return Err(AppError::WriteInterval); } @@ -1580,7 +1581,8 @@ pub(crate) async fn post( if is_author && (inn.limit_edit_seconds == 0 - || post.created_at + (inn.limit_edit_seconds as i64) >= Utc::now().timestamp()) + || post.created_at + (inn.limit_edit_seconds as i64) + >= Timestamp::now().as_second()) { can_edit = true; } @@ -1619,7 +1621,7 @@ pub(crate) async fn post( PostStatus::HiddenByMod => "

Hidden by mod.

".into(), PostStatus::HiddenByUser => "

Hidden by user.

".into(), _ => { - let diff = (Utc::now().timestamp() - post.created_at) / 24 / 3600; + let diff = (Timestamp::now().as_second() - post.created_at) / 24 / 3600; if diff > 30 { let mut content = format!( r#" @@ -1799,7 +1801,7 @@ pub(crate) async fn comment_post( return Err(AppError::NotFound); } - let created_at = Utc::now().timestamp(); + let created_at = Timestamp::now().as_second(); if created_at - claim.last_write < site_config.comment_interval { return Err(AppError::WriteInterval); } diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 88797f93..8a596243 100644 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -138,8 +138,8 @@ use crate::error::AppError; use ::tantivy::TantivyDocument; use bincode::config::standard; use bincode::{Decode, Encode}; -use chrono::{Days, Utc}; use garde::Validate; +use jiff::{RoundMode, Timestamp, TimestampRound, ToSpan, Unit}; use serde::{Deserialize, Serialize}; use sled::Db; use std::fmt::Display; @@ -204,14 +204,16 @@ impl User { } fn update_stats(db: &Db, uid: u32, stat_type: &str) -> Result<(), AppError> { - let expire = Utc::now() - .date_naive() - .checked_add_days(Days::new(3)) + let expire = Timestamp::now() + .round( + TimestampRound::new() + .smallest(Unit::Day) + .mode(RoundMode::Trunc), + ) .unwrap() - .and_hms_opt(0, 0, 0) + .checked_add(3.day()) .unwrap() - .and_utc() - .timestamp(); + .as_second(); let key = format!("{expire:x}_{uid}_{stat_type}"); incr_id(&db.open_tree("user_stats")?, key)?; Ok(()) diff --git a/src/controller/solo.rs b/src/controller/solo.rs index 801f7cfe..bcf1de94 100644 --- a/src/controller/solo.rs +++ b/src/controller/solo.rs @@ -23,8 +23,8 @@ use axum_extra::{ TypedHeader, }; use axum_garde::WithValidation; -use chrono::Utc; use garde::Validate; +use jiff::Timestamp; use serde::Deserialize; use sled::Db; use tracing::warn; @@ -395,7 +395,7 @@ pub(crate) async fn solo_post( } } - let created_at = Utc::now().timestamp(); + let created_at = Timestamp::now().as_second(); if created_at - claim.last_write < site_config.solo_interval { return Err(AppError::WriteInterval); } diff --git a/src/controller/user.rs b/src/controller/user.rs index e0588141..38827be1 100644 --- a/src/controller/user.rs +++ b/src/controller/user.rs @@ -23,10 +23,10 @@ use axum_extra::{headers::Cookie, TypedHeader}; use axum_garde::WithValidation; use bincode::config::standard; use captcha::{CaptchaName, Difficulty}; -use chrono::Utc; use data_encoding::BASE64; use garde::Validate; use identicon::Identicon; +use jiff::Timestamp; use ring::{ pbkdf2, rand::{self, SecureRandom}, @@ -950,7 +950,7 @@ pub(crate) async fn signup_post( let avatar = format!("{}/{}.png", &CONFIG.avatars_path, uid); Identicon::new(&generate_salt()).image().save(avatar)?; - let created_at = Utc::now().timestamp(); + let created_at = Timestamp::now().as_second(); let role = if uid == 1 { Role::Admin } else { @@ -1108,9 +1108,9 @@ impl Claim { let timestamp = session.split_once('_')?.0; let tree = &db.open_tree("sessions").ok()?; let timestamp = i64::from_str_radix(timestamp, 16).ok()?; - let now = Utc::now(); + let now = Timestamp::now(); - if timestamp < now.timestamp() { + if timestamp < now.as_second() { tree.remove(session).ok()?; return None; } @@ -1129,7 +1129,7 @@ impl Claim { } pub(super) fn update_last_write(mut self, db: &Db) -> Result<(), AppError> { - self.last_write = Utc::now().timestamp(); + self.last_write = Timestamp::now().as_second(); set_one_with_key(db, "sessions", &self.session_id, &self)?; Ok(()) @@ -1157,7 +1157,7 @@ impl Claim { return Err(AppError::Banned); } let seconds = expire_seconds(expiry); - let now = Utc::now().timestamp(); + let now = Timestamp::now().as_second(); let session_id = generate_nanoid_ttl(seconds); let claim = Claim {