Files
rs_toolsbox/src/time/mod.rs

148 lines
5.8 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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()
}