148 lines
5.8 KiB
Rust
148 lines
5.8 KiB
Rust
use chrono::{DateTime, Datelike, Duration, FixedOffset, NaiveDate, NaiveDateTime, TimeZone, Utc};
|
||
|
||
/// 获取一个类型为`chrono::DateTime<chrono::FixedOffset>`类型的当前日期时间的实例。时间时区将自动被设置为东八区。
|
||
pub fn now_asia_shanghai() -> DateTime<FixedOffset> {
|
||
let utc_now = Utc::now();
|
||
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(),
|
||
)
|
||
}
|
||
}
|
||
|
||
/// 将一个类型为`chrono::DateTime<chrono::Utc>`类型的日期时间转换到东八区的时间实例。
|
||
pub fn shift_to_asia_shanghai<T: TimeZone>(datetime: DateTime<T>) -> DateTime<FixedOffset> {
|
||
shift_tz(datetime, 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(),
|
||
)
|
||
}
|
||
|
||
/// 从一个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(),
|
||
)
|
||
}
|
||
|
||
/// 根据指定的日期生成一个时间对象,如果给定的日期不合法将返回空白内容。
|
||
///
|
||
/// - `year`:日期的年份。
|
||
/// - `month`:日期的月份,从`1`开始。
|
||
/// - `day`:日期的天数。
|
||
pub fn date(year: i32, month: u32, day: u32) -> Option<NaiveDate> {
|
||
NaiveDate::from_ymd_opt(year, month, day)
|
||
}
|
||
|
||
/// 根据指定日期生成一个指定日期最开始时间的时间,精度为毫秒。
|
||
///
|
||
/// - `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))
|
||
}
|
||
|
||
/// 根据给定的日期,返回其当天最开始的时间,精度为毫秒。
|
||
///
|
||
/// - `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))
|
||
}
|
||
|
||
/// 根据给定的日期,返回其当天即将结束的时间,精度为毫秒。
|
||
///
|
||
/// - `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))
|
||
}
|
||
|
||
/// 根据指定日期生成一个指定日期结束时间的时间,精度为毫秒。
|
||
///
|
||
/// - `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))
|
||
}
|
||
|
||
/// 返回两个日期之间的月份差值。
|
||
///
|
||
/// - `control`:基准月份。
|
||
/// - `test`:测试月份。
|
||
pub fn difference_month(control: NaiveDate, test: NaiveDate) -> i32 {
|
||
let difference_year = test.year() - control.year();
|
||
let difference_month = (test.month() - control.month()) as i32;
|
||
difference_year * 12 + difference_month
|
||
}
|
||
|
||
/// 测试指定月份是否是基准月份的前一个月份。
|
||
///
|
||
/// - `control`:基准月份。
|
||
/// - `test`:待测试的指定月份。
|
||
pub fn is_previous_month(control: NaiveDate, test: NaiveDate) -> bool {
|
||
difference_month(control, test) == 1
|
||
}
|
||
|
||
/// 测试指定月份是否是基准月份的下一个月份。
|
||
///
|
||
/// - `control`:基准月份。
|
||
/// - `test`:待测试的指定月份。
|
||
pub fn is_next_month(control: NaiveDate, test: NaiveDate) -> bool {
|
||
difference_month(control, test) == -1
|
||
}
|
||
|
||
/// 生成符合Postgresql中日期类型最小值的日期。
|
||
pub fn min_date() -> NaiveDate {
|
||
NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()
|
||
}
|
||
|
||
/// 生成符合Postgresql中日期类型最小值的日期时间。
|
||
pub fn min_datetime() -> DateTime<FixedOffset> {
|
||
NaiveDate::from_ymd_opt(1970, 1, 1)
|
||
.map(begin_of_date)
|
||
.flatten()
|
||
.unwrap()
|
||
}
|
||
|
||
/// 生成符合Postgresql中日期类型最大值的日期。
|
||
pub fn max_date() -> NaiveDate {
|
||
NaiveDate::from_ymd_opt(2099, 12, 31).unwrap()
|
||
}
|
||
|
||
/// 生成符合Postgresql中日期类型最大值的日期时间。
|
||
pub fn max_datetime() -> DateTime<FixedOffset> {
|
||
NaiveDate::from_ymd_opt(2099, 12, 31)
|
||
.map(end_of_date)
|
||
.flatten()
|
||
.unwrap()
|
||
}
|