feat(time): 替换 chrono 为 time 库以优化时间处理
- 移除 chrono 依赖,引入 time 库并启用相关特性 - 重构时间工具模块,使用 OffsetDateTime 替代 DateTime - 更新时间生成、转换和解析逻辑,提升代码一致性与可维护性 - 调整日期构造函数参数类型,增强类型安全 - 修正时间戳生成方式,确保东八区时间正确表示
This commit is contained in:
11
Cargo.toml
11
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"] }
|
||||
|
@@ -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<i64> = Lazy::new(|| {
|
||||
const HAIL_PERIOD_START: LazyLock<i64> = 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<HailSerialCodeAlgorithm> = OnceCell::new();
|
||||
static INSTANCE: OnceLock<HailSerialCodeAlgorithm> = 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
|
||||
}
|
||||
|
||||
|
108
src/time/mod.rs
108
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<chrono::FixedOffset>`类型的当前日期时间的实例。时间时区将自动被设置为东八区。
|
||||
pub fn now_asia_shanghai() -> DateTime<FixedOffset> {
|
||||
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<chrono::Utc>`类型的日期时间转换到指定时区的时间实例。
|
||||
pub fn shift_tz<T: TimeZone>(datetime: DateTime<T>, zone: i64) -> DateTime<FixedOffset> {
|
||||
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<chrono::Utc>`类型的日期时间转换到东八区的时间实例。
|
||||
pub fn shift_to_asia_shanghai<T: TimeZone>(datetime: DateTime<T>) -> DateTime<FixedOffset> {
|
||||
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<FixedOffset> {
|
||||
DateTime::<FixedOffset>::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<FixedOffset> {
|
||||
let request_time = NaiveDateTime::from_timestamp_micros(timestamp).unwrap();
|
||||
DateTime::<FixedOffset>::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<FixedOffset> {
|
||||
/// - `year`:日期的年份。
|
||||
/// - `month`:日期的月份,从`1`开始。
|
||||
/// - `day`:日期的天数。
|
||||
pub fn date(year: i32, month: u32, day: u32) -> Option<NaiveDate> {
|
||||
NaiveDate::from_ymd_opt(year, month, day)
|
||||
pub fn date(year: i32, month: u8, day: u8) -> Option<Date> {
|
||||
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<NaiveDate> {
|
||||
/// - `year`:指定日期的年份。
|
||||
/// - `month`:指定日期的月份,从`1`开始。
|
||||
/// - `day`:指定日期的天数。
|
||||
pub fn date_beginning(year: i32, month: u32, day: u32) -> Option<DateTime<FixedOffset>> {
|
||||
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::<FixedOffset>::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<DateTime<FixedOffset>> {
|
||||
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::<FixedOffset>::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<DateTime<FixedOffset>> {
|
||||
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::<FixedOffset>::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<DateTime<FixedOffset>> {
|
||||
/// - `year`:指定日期的年份。
|
||||
/// - `month`:指定日期的月份,从`1`开始。
|
||||
/// - `day`:指定日期的天数。
|
||||
pub fn date_ending(year: i32, month: u32, day: u32) -> Option<DateTime<FixedOffset>> {
|
||||
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::<FixedOffset>::from_local(dt, timezone))
|
||||
pub fn date_ending(year: i32, month: u8, day: u8) -> Option<OffsetDateTime> {
|
||||
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<FixedOffset> {
|
||||
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<FixedOffset> {
|
||||
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()
|
||||
}
|
||||
|
Reference in New Issue
Block a user