From 21892e977f064aa92dc213eeb189a97813aa664a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=B6=9B?= Date: Thu, 9 Oct 2025 15:04:44 +0800 Subject: [PATCH] =?UTF-8?q?feat(time):=20=E6=9B=BF=E6=8D=A2=20chrono=20?= =?UTF-8?q?=E4=B8=BA=20time=20=E5=BA=93=E4=BB=A5=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 chrono 依赖,引入 time 库并启用相关特性 - 重构时间工具模块,使用 OffsetDateTime 替代 DateTime - 更新时间生成、转换和解析逻辑,提升代码一致性与可维护性 - 调整日期构造函数参数类型,增强类型安全 - 修正时间戳生成方式,确保东八区时间正确表示 --- Cargo.toml | 11 +++- src/serial_code/hail.rs | 20 ++++---- src/time/mod.rs | 108 +++++++++++++++++----------------------- 3 files changed, 64 insertions(+), 75 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7770032..6590162 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,6 @@ blake2b_simd = "1.0.3" blake3 = { version = "1.8.2", features = ["serde", "digest"] } blockhash = "1.0.0" cbc = { version = "0.1.2", features = ["std"] } -chrono = "0.4.26" cipher = "0.4.4" des = "0.8.1" hex = "0.4.3" @@ -23,10 +22,18 @@ hmac-sha256 = "1.1.12" hmac-sha512 = "1.1.7" image = "0.25.8" md-5 = "0.10.6" -once_cell = "1.21.3" rand = "0.8.5" rsa = { version = "0.9.2", features = ["sha2"] } sha1 = "0.10.6" sha2 = "0.10.9" thiserror = "2.0.17" +time = { version = "0.3.44", features = [ + "formatting", + "local-offset", + "macros", + "parsing", + "rand", + "serde", + "serde-human-readable", +] } uuid = { version = "1.18.1", features = ["v4", "fast-rng"] } diff --git a/src/serial_code/hail.rs b/src/serial_code/hail.rs index d349f78..d4f40a0 100644 --- a/src/serial_code/hail.rs +++ b/src/serial_code/hail.rs @@ -1,22 +1,20 @@ use core::time; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, LazyLock, Mutex, OnceLock}; -use chrono::NaiveDateTime; -use once_cell::sync::{Lazy, OnceCell}; +use ::time::{macros::datetime, OffsetDateTime}; use thiserror::Error; -const HAIL_PERIOD_START: Lazy = Lazy::new(|| { +const HAIL_PERIOD_START: LazyLock = LazyLock::new(|| { crate::time::date(2022, 2, 22) - .map(|d| d.and_hms_opt(22, 22, 22)) - .flatten() - .map(|dt| crate::time::attach_asia_shanghai(dt)) - .map(|dt| dt.timestamp()) - .unwrap_or_else(|| NaiveDateTime::MIN.timestamp()) + .map(|d| d.with_hms_nano(22, 22, 22, 222_222_222).unwrap()) + .map(crate::time::attach_asia_shanghai) + .map(OffsetDateTime::unix_timestamp) + .unwrap_or_else(|| datetime!(1970-01-01 0:00 +8).unix_timestamp()) }); type TimestampValidator = fn(i64) -> bool; type TimestampGenerator = fn() -> i64; -static INSTANCE: OnceCell = OnceCell::new(); +static INSTANCE: OnceLock = OnceLock::new(); #[derive(Debug, Error)] pub enum HailSerialCodeAlgorithmError { @@ -65,7 +63,7 @@ impl HailSerialCodeAlgorithm { /// 生成一个自计时起点以来的时间戳。 fn generate_timestamp(&self) -> i64 { - let current_time = crate::time::now_asia_shanghai().timestamp(); + let current_time = crate::time::now_asia_shanghai().unix_timestamp(); current_time - *HAIL_PERIOD_START } diff --git a/src/time/mod.rs b/src/time/mod.rs index 056ec36..ffdb301 100644 --- a/src/time/mod.rs +++ b/src/time/mod.rs @@ -1,46 +1,36 @@ -use chrono::{DateTime, Datelike, Duration, FixedOffset, NaiveDate, NaiveDateTime, TimeZone, Utc}; +use std::i64; + +use time::{macros::offset, Date, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcOffset}; /// 获取一个类型为`chrono::DateTime`类型的当前日期时间的实例。时间时区将自动被设置为东八区。 -pub fn now_asia_shanghai() -> DateTime { - let utc_now = Utc::now(); +pub fn now_asia_shanghai() -> OffsetDateTime { + let utc_now = OffsetDateTime::now_utc(); shift_to_asia_shanghai(utc_now) } /// 将一个类型为`chrono::DateTime`类型的日期时间转换到指定时区的时间实例。 -pub fn shift_tz(datetime: DateTime, zone: i64) -> DateTime { - if zone.is_positive() { - datetime.with_timezone( - &FixedOffset::east_opt(Duration::hours(zone.abs()).num_seconds() as i32).unwrap(), - ) - } else { - datetime.with_timezone( - &FixedOffset::west_opt(Duration::hours(zone.abs()).num_seconds() as i32).unwrap(), - ) - } +pub fn shift_tz(datetime: OffsetDateTime, zone: i8) -> OffsetDateTime { + datetime.to_offset(UtcOffset::from_hms(zone.clamp(-25, 25), 0, 0).unwrap()) } /// 将一个类型为`chrono::DateTime`类型的日期时间转换到东八区的时间实例。 -pub fn shift_to_asia_shanghai(datetime: DateTime) -> DateTime { - shift_tz(datetime, 8) +pub fn shift_to_asia_shanghai(datetime: OffsetDateTime) -> OffsetDateTime { + datetime.to_offset(offset!(+8)) } /// 直接给一个原生日期时间附加东八区的时区信息。 -pub fn attach_asia_shanghai(datetime: NaiveDateTime) -> DateTime { - DateTime::::from_local( - datetime, - FixedOffset::east_opt(Duration::hours(8).num_seconds() as i32).unwrap(), - ) +pub fn attach_asia_shanghai(datetime: PrimitiveDateTime) -> OffsetDateTime { + let utc_date_time = datetime.as_utc(); + let offseted_date_time = OffsetDateTime::from(utc_date_time); + offseted_date_time.replace_offset(offset!(+8)) } /// 从一个64位时间戳生成东八区的时间实例。这个函数主要用于处理使用`timestamp`方法直接返回的时间戳。 /// /// - `timestamp`:64位时间戳。 -pub fn from_utc_timestamp(timestamp: i64) -> DateTime { - let request_time = NaiveDateTime::from_timestamp_micros(timestamp).unwrap(); - DateTime::::from_utc( - request_time, - FixedOffset::east_opt(Duration::hours(8).num_seconds() as i32).unwrap(), - ) +pub fn from_utc_timestamp(timestamp: i64) -> OffsetDateTime { + let request_time = OffsetDateTime::from_unix_timestamp(timestamp.clamp(0, i64::MAX)).unwrap(); + request_time.to_offset(offset!(+8)) } /// 根据指定的日期生成一个时间对象,如果给定的日期不合法将返回空白内容。 @@ -48,8 +38,8 @@ pub fn from_utc_timestamp(timestamp: i64) -> DateTime { /// - `year`:日期的年份。 /// - `month`:日期的月份,从`1`开始。 /// - `day`:日期的天数。 -pub fn date(year: i32, month: u32, day: u32) -> Option { - NaiveDate::from_ymd_opt(year, month, day) +pub fn date(year: i32, month: u8, day: u8) -> Option { + Date::from_calendar_date(year, Month::try_from(month.clamp(1, 12)).unwrap(), day).ok() } /// 根据指定日期生成一个指定日期最开始时间的时间,精度为毫秒。 @@ -57,29 +47,26 @@ pub fn date(year: i32, month: u32, day: u32) -> Option { /// - `year`:指定日期的年份。 /// - `month`:指定日期的月份,从`1`开始。 /// - `day`:指定日期的天数。 -pub fn date_beginning(year: i32, month: u32, day: u32) -> Option> { - let timezone = FixedOffset::east_opt(Duration::hours(8).num_seconds() as i32).unwrap(); - NaiveDate::from_ymd_opt(year, month, day) - .map(|d| d.and_hms_micro_opt(0, 0, 0, 0).unwrap()) - .map(|dt| DateTime::::from_local(dt, timezone)) +pub fn date_beginning(year: i32, month: u8, day: u8) -> OffsetDateTime { + OffsetDateTime::new_in_offset( + Date::from_calendar_date(year, Month::try_from(month.clamp(1, 12)).unwrap(), day).unwrap(), + Time::MIDNIGHT, + offset!(+8), + ) } /// 根据给定的日期,返回其当天最开始的时间,精度为毫秒。 /// /// - `date`:给定的原始日期,注意:原始日期将被消耗掉。 -pub fn begin_of_date(date: NaiveDate) -> Option> { - let timezone = FixedOffset::east_opt(Duration::hours(8).num_seconds() as i32).unwrap(); - date.and_hms_micro_opt(0, 0, 0, 0) - .map(|dt| DateTime::::from_local(dt, timezone)) +pub fn begin_of_date(date: Date) -> OffsetDateTime { + OffsetDateTime::new_in_offset(date, Time::MIDNIGHT, offset!(+8)) } /// 根据给定的日期,返回其当天即将结束的时间,精度为毫秒。 /// /// - `date`:给定的原始日期,注意:原始日期将被消耗掉。 -pub fn end_of_date(date: NaiveDate) -> Option> { - let timezone = FixedOffset::east_opt(Duration::hours(8).num_seconds() as i32).unwrap(); - date.and_hms_micro_opt(23, 59, 59, 999_999) - .map(|dt| DateTime::::from_local(dt, timezone)) +pub fn end_of_date(date: Date) -> OffsetDateTime { + OffsetDateTime::new_in_offset(date, Time::MAX, offset!(+8)) } /// 根据指定日期生成一个指定日期结束时间的时间,精度为毫秒。 @@ -87,20 +74,19 @@ pub fn end_of_date(date: NaiveDate) -> Option> { /// - `year`:指定日期的年份。 /// - `month`:指定日期的月份,从`1`开始。 /// - `day`:指定日期的天数。 -pub fn date_ending(year: i32, month: u32, day: u32) -> Option> { - let timezone = FixedOffset::east_opt(Duration::hours(8).num_seconds() as i32).unwrap(); - NaiveDate::from_ymd_opt(year, month, day) - .map(|d| d.and_hms_micro_opt(23, 59, 59, 999_999).unwrap()) - .map(|dt| DateTime::::from_local(dt, timezone)) +pub fn date_ending(year: i32, month: u8, day: u8) -> Option { + Date::from_calendar_date(year, Month::try_from(month.clamp(1, 12)).unwrap(), day) + .ok() + .map(end_of_date) } /// 返回两个日期之间的月份差值。 /// /// - `control`:基准月份。 /// - `test`:测试月份。 -pub fn difference_month(control: NaiveDate, test: NaiveDate) -> i32 { +pub fn difference_month(control: Date, test: Date) -> i32 { let difference_year = test.year() - control.year(); - let difference_month = (test.month() - control.month()) as i32; + let difference_month = u8::from(test.month()) as i32 - u8::from(control.month()) as i32; difference_year * 12 + difference_month } @@ -108,40 +94,38 @@ pub fn difference_month(control: NaiveDate, test: NaiveDate) -> i32 { /// /// - `control`:基准月份。 /// - `test`:待测试的指定月份。 -pub fn is_previous_month(control: NaiveDate, test: NaiveDate) -> bool { - difference_month(control, test) == 1 +pub fn is_previous_month(control: Date, test: Date) -> bool { + control.month().previous() == test.month() } /// 测试指定月份是否是基准月份的下一个月份。 /// /// - `control`:基准月份。 /// - `test`:待测试的指定月份。 -pub fn is_next_month(control: NaiveDate, test: NaiveDate) -> bool { - difference_month(control, test) == -1 +pub fn is_next_month(control: Date, test: Date) -> bool { + control.month().next() == test.month() } /// 生成符合Postgresql中日期类型最小值的日期。 -pub fn min_date() -> NaiveDate { - NaiveDate::from_ymd_opt(1970, 1, 1).unwrap() +pub fn min_date() -> Date { + Date::from_calendar_date(1970, Month::January, 1).unwrap() } /// 生成符合Postgresql中日期类型最小值的日期时间。 -pub fn min_datetime() -> DateTime { - NaiveDate::from_ymd_opt(1970, 1, 1) +pub fn min_datetime() -> OffsetDateTime { + Date::from_calendar_date(1970, Month::January, 1) .map(begin_of_date) - .flatten() .unwrap() } /// 生成符合Postgresql中日期类型最大值的日期。 -pub fn max_date() -> NaiveDate { - NaiveDate::from_ymd_opt(2099, 12, 31).unwrap() +pub fn max_date() -> Date { + Date::from_calendar_date(2099, Month::December, 31).unwrap() } /// 生成符合Postgresql中日期类型最大值的日期时间。 -pub fn max_datetime() -> DateTime { - NaiveDate::from_ymd_opt(2099, 12, 31) +pub fn max_datetime() -> OffsetDateTime { + Date::from_calendar_date(2099, Month::December, 31) .map(end_of_date) - .flatten() .unwrap() }