date_formatter/
utils.rs

1use std::time::{SystemTime, UNIX_EPOCH};
2use std::fmt;
3
4/// 自定义日期结构体
5#[derive(Debug)]
6pub struct Date {
7    year: u16,
8    month: u8,
9    day: u8,
10}
11
12impl Date {
13    /// 创建一个新的日期
14    pub fn new(year: u16, month: u8, day: u8) -> Option<Self> {
15        if month < 1 || month > 12 || day < 1 || day > 31 {
16            return None;
17        }
18        Some(Date { year, month, day })
19    }
20}
21
22impl fmt::Display for Date {
23    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24        write!(f, "{:04}-{:02}-{:02}", self.year, self.month, self.day)
25    }
26}
27
28
29/// 将 SystemTime 转换为年、月、日、时、分、秒、毫秒
30fn system_time_to_units(time: SystemTime) -> (u16, u8, u8, u8, u8, u8, u16) {
31    let duration = time.duration_since(UNIX_EPOCH).expect("Time went backwards");
32    let secs = duration.as_secs();
33    let nanos = duration.subsec_nanos();
34
35    // 计算天数
36    let days_since_epoch = secs / 86400;
37    let remaining_secs = secs % 86400;
38
39    // 从 1970-01-01 开始计算
40    let mut year = 1970;
41    let mut remaining_days = days_since_epoch as i64;
42
43    loop {
44        let is_leap_year = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
45        let days_in_year = if is_leap_year { 366 } else { 365 };
46
47        if remaining_days < days_in_year {
48            break;
49        }
50
51        remaining_days -= days_in_year;
52        year += 1;
53    }
54
55    let is_leap_year = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
56    let days_in_month = [
57        31,
58        if is_leap_year { 29 } else { 28 },
59        31,
60        30,
61        31,
62        30,
63        31,
64        31,
65        30,
66        31,
67        30,
68        31,
69    ];
70
71    let mut month = 1;
72    for &days in &days_in_month {
73        if remaining_days < days as i64 {
74            break;
75        }
76        remaining_days -= days as i64;
77        month += 1;
78    }
79
80    let day = remaining_days as u8 + 1;
81
82    // 计算时、分、秒
83    let hour = (remaining_secs / 3600) as u8;
84    let minute = ((remaining_secs % 3600) / 60) as u8;
85    let second = (remaining_secs % 60) as u8;
86
87    // 计算毫秒
88    let millisecond = (nanos / 1_000_000) as u16;
89
90    (year as u16, month as u8, day, hour, minute, second, millisecond)
91}
92
93/// 将 SystemTime 格式化为字符串 年月日
94pub fn format_date(time: SystemTime, format: &str) -> String {
95    let (year, month, day,_,_,_,_) = system_time_to_units(time);
96
97    // 格式化
98    format
99        .replace("%Y", &year.to_string())
100        .replace("%m", &format!("{:02}", month))
101        .replace("%d", &format!("{:02}", day))
102}
103
104/// 将字符串解析为日期Date
105pub fn parse_date(date_str: &str) -> Result<Date, &'static str> {
106    let parts: Vec<&str> = date_str.split('-').collect();
107    if parts.len() != 3 {
108        return Err("Invalid date format");
109    }
110
111    let year = parts[0].parse().map_err(|_| "Invalid year")?;
112    let month = parts[1].parse().map_err(|_| "Invalid month")?;
113    let day = parts[2].parse().map_err(|_| "Invalid day")?;
114
115    Date::new(year, month, day).ok_or("Invalid date")
116}
117
118/// 计算两个 SystemTime 之间的天数差异
119pub fn days_between(time1: SystemTime, time2: SystemTime) -> i64 {
120    let duration1 = time1
121        .duration_since(UNIX_EPOCH)
122        .expect("Time went backwards");
123    let duration2 = time2
124        .duration_since(UNIX_EPOCH)
125        .expect("Time went backwards");
126
127    let secs1 = duration1.as_secs();
128    let secs2 = duration2.as_secs();
129
130    let days1 = secs1 / 86400;
131    let days2 = secs2 / 86400;
132
133    (days1 as i64 - days2 as i64).abs()
134}
135
136
137/// 格式化模板枚举
138/// 格式化模板枚举
139/// 格式化模板枚举
140pub enum DateFormat {
141    YearMonthDay,       // %Y-%m-%d
142    YearMonthDayNoLine,   // %Y%m%d
143    YearMonthDayChinese, // %Y年%m月%d日
144    MonthDayYear,       // %m/%d/%Y
145    DayMonthYear,       // %d-%m-%Y
146    DateTime,           // %Y-%m-%d %H:%M:%S
147    DateTimeWithMillis, // %Y-%m-%d %H:%M:%S.%f
148}
149
150/// 根据时间戳和格式化模板返回格式化后的日期字符串
151use chrono::{DateTime, Local, TimeZone, Utc};
152pub fn format_timestamp(timestamp: u64, format: DateFormat) -> String {
153    // 将时间戳转换为 UTC 时间
154    let utc_datetime: DateTime<Utc> = Utc.timestamp_opt(timestamp as i64, 0).unwrap();
155    // 将 UTC 时间转换为本地时间(自动获取系统时区)
156    let local_datetime: DateTime<Local> = utc_datetime.with_timezone(&Local);
157    match format {
158        DateFormat::YearMonthDay => local_datetime.format("%Y-%m-%d").to_string(),
159        DateFormat::YearMonthDayNoLine => local_datetime.format("%Y%m%d").to_string(),
160        DateFormat::YearMonthDayChinese => local_datetime.format("%Y年%m月%d日").to_string(),
161        DateFormat::MonthDayYear => local_datetime.format("%m/%d/%Y").to_string(),
162        DateFormat::DayMonthYear => local_datetime.format("%d-%m-%Y").to_string(),
163        DateFormat::DateTime => local_datetime.format("%Y-%m-%d %H:%M:%S").to_string(),
164        DateFormat::DateTimeWithMillis => local_datetime.format("%Y-%m-%d %H:%M:%S%.3f").to_string(),
165    }
166}