date_formatter/
utils.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
use std::time::{SystemTime, UNIX_EPOCH};
use std::fmt;

/// 自定义日期结构体
#[derive(Debug)]
pub struct Date {
    year: u16,
    month: u8,
    day: u8,
}

impl Date {
    /// 创建一个新的日期
    pub fn new(year: u16, month: u8, day: u8) -> Option<Self> {
        if month < 1 || month > 12 || day < 1 || day > 31 {
            return None;
        }
        Some(Date { year, month, day })
    }
}

impl fmt::Display for Date {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:04}-{:02}-{:02}", self.year, self.month, self.day)
    }
}


/// 将 SystemTime 转换为年、月、日、时、分、秒、毫秒
fn system_time_to_units(time: SystemTime) -> (u16, u8, u8, u8, u8, u8, u16) {
    let duration = time.duration_since(UNIX_EPOCH).expect("Time went backwards");
    let secs = duration.as_secs();
    let nanos = duration.subsec_nanos();

    // 计算天数
    let days_since_epoch = secs / 86400;
    let remaining_secs = secs % 86400;

    // 从 1970-01-01 开始计算
    let mut year = 1970;
    let mut remaining_days = days_since_epoch as i64;

    loop {
        let is_leap_year = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
        let days_in_year = if is_leap_year { 366 } else { 365 };

        if remaining_days < days_in_year {
            break;
        }

        remaining_days -= days_in_year;
        year += 1;
    }

    let is_leap_year = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
    let days_in_month = [
        31,
        if is_leap_year { 29 } else { 28 },
        31,
        30,
        31,
        30,
        31,
        31,
        30,
        31,
        30,
        31,
    ];

    let mut month = 1;
    for &days in &days_in_month {
        if remaining_days < days as i64 {
            break;
        }
        remaining_days -= days as i64;
        month += 1;
    }

    let day = remaining_days as u8 + 1;

    // 计算时、分、秒
    let hour = (remaining_secs / 3600) as u8;
    let minute = ((remaining_secs % 3600) / 60) as u8;
    let second = (remaining_secs % 60) as u8;

    // 计算毫秒
    let millisecond = (nanos / 1_000_000) as u16;

    (year as u16, month as u8, day, hour, minute, second, millisecond)
}

/// 将 SystemTime 格式化为字符串 年月日
pub fn format_date(time: SystemTime, format: &str) -> String {
    let (year, month, day,_,_,_,_) = system_time_to_units(time);

    // 格式化
    format
        .replace("%Y", &year.to_string())
        .replace("%m", &format!("{:02}", month))
        .replace("%d", &format!("{:02}", day))
}

/// 将字符串解析为日期Date
pub fn parse_date(date_str: &str) -> Result<Date, &'static str> {
    let parts: Vec<&str> = date_str.split('-').collect();
    if parts.len() != 3 {
        return Err("Invalid date format");
    }

    let year = parts[0].parse().map_err(|_| "Invalid year")?;
    let month = parts[1].parse().map_err(|_| "Invalid month")?;
    let day = parts[2].parse().map_err(|_| "Invalid day")?;

    Date::new(year, month, day).ok_or("Invalid date")
}

/// 计算两个 SystemTime 之间的天数差异
pub fn days_between(time1: SystemTime, time2: SystemTime) -> i64 {
    let duration1 = time1
        .duration_since(UNIX_EPOCH)
        .expect("Time went backwards");
    let duration2 = time2
        .duration_since(UNIX_EPOCH)
        .expect("Time went backwards");

    let secs1 = duration1.as_secs();
    let secs2 = duration2.as_secs();

    let days1 = secs1 / 86400;
    let days2 = secs2 / 86400;

    (days1 as i64 - days2 as i64).abs()
}


/// 格式化模板枚举
/// 格式化模板枚举
/// 格式化模板枚举
pub enum DateFormat {
    YearMonthDay,       // %Y-%m-%d
    YearMonthDayNoLine,   // %Y%m%d
    YearMonthDayChinese, // %Y年%m月%d日
    MonthDayYear,       // %m/%d/%Y
    DayMonthYear,       // %d-%m-%Y
    DateTime,           // %Y-%m-%d %H:%M:%S
    DateTimeWithMillis, // %Y-%m-%d %H:%M:%S.%f
}

/// 根据时间戳和格式化模板返回格式化后的日期字符串
pub fn format_timestamp(timestamp: u64, format: DateFormat) -> String {
    let datetime = UNIX_EPOCH + std::time::Duration::from_secs(timestamp);
    let (year, month, day, hour, minute, second, millisecond) = system_time_to_units(datetime);

    match format {
        DateFormat::YearMonthDay => format!("{:04}-{:02}-{:02}", year, month, day),
        DateFormat::YearMonthDayNoLine => format!("{:04}{:02}{:02}", year, month, day),
        DateFormat::YearMonthDayChinese => format!("{:04}年{:02}月{:02}日", year, month, day),
        DateFormat::MonthDayYear => format!("{:02}/{:02}/{:04}", month, day, year),
        DateFormat::DayMonthYear => format!("{:02}-{:02}-{:04}", day, month, year),
        DateFormat::DateTime => format!(
            "{:04}-{:02}-{:02} {:02}:{:02}:{:02}",
            year, month, day, hour, minute, second
        ),
        DateFormat::DateTimeWithMillis => format!(
            "{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}",
            year, month, day, hour, minute, second, millisecond
        ),
    }
}