baichun_framework_core/utils/
time.rs

1// ruoyi-common/src/utils/time.rs
2//! 时间处理工具模块
3
4use chrono::{DateTime, Local, NaiveDateTime, TimeZone, Utc};
5use serde::Deserialize;
6use std::time::{SystemTime, UNIX_EPOCH};
7
8/// 时间工具
9pub struct TimeUtils;
10
11impl TimeUtils {
12    /// 获取当前时间戳(秒)
13    pub fn current_timestamp() -> i64 {
14        SystemTime::now()
15            .duration_since(UNIX_EPOCH)
16            .unwrap()
17            .as_secs() as i64
18    }
19
20    /// 获取当前时间戳(毫秒)
21    pub fn current_timestamp_millis() -> i64 {
22        SystemTime::now()
23            .duration_since(UNIX_EPOCH)
24            .unwrap()
25            .as_millis() as i64
26    }
27
28    /// 获取当前日期时间字符串
29    pub fn current_datetime_str() -> String {
30        Local::now().format("%Y-%m-%d %H:%M:%S").to_string()
31    }
32
33    /// 获取当前日期字符串
34    pub fn current_date_str() -> String {
35        Local::now().format("%Y-%m-%d").to_string()
36    }
37
38    /// 获取当前时间字符串
39    pub fn current_time_str() -> String {
40        Local::now().format("%H:%M:%S").to_string()
41    }
42
43    /// 时间戳转日期时间字符串
44    pub fn timestamp_to_datetime_str(timestamp: i64) -> String {
45        DateTime::<Utc>::from_timestamp(timestamp, 0)
46            .unwrap()
47            .with_timezone(&Local)
48            .format("%Y-%m-%d %H:%M:%S")
49            .to_string()
50    }
51
52    /// 日期时间字符串转时间戳
53    pub fn datetime_str_to_timestamp(datetime_str: &str) -> Option<i64> {
54        let naive = NaiveDateTime::parse_from_str(datetime_str, "%Y-%m-%d %H:%M:%S").ok()?;
55        let datetime = Local.from_local_datetime(&naive).single()?;
56        Some(datetime.timestamp())
57    }
58
59    /// 格式化日期时间
60    pub fn format_datetime(datetime: DateTime<Local>, format: &str) -> String {
61        datetime.format(format).to_string()
62    }
63
64    /// 解析日期时间字符串
65    pub fn parse_datetime(datetime_str: &str, format: &str) -> Option<DateTime<Local>> {
66        let naive = NaiveDateTime::parse_from_str(datetime_str, format).ok()?;
67        Local.from_local_datetime(&naive).single()
68    }
69
70    /// 计算两个时间的差值(秒)
71    pub fn diff_seconds(start: DateTime<Local>, end: DateTime<Local>) -> i64 {
72        end.timestamp() - start.timestamp()
73    }
74
75    /// 增加秒数
76    pub fn add_seconds(datetime: DateTime<Local>, seconds: i64) -> DateTime<Local> {
77        datetime + chrono::Duration::seconds(seconds)
78    }
79
80    /// 增加分钟
81    pub fn add_minutes(datetime: DateTime<Local>, minutes: i64) -> DateTime<Local> {
82        datetime + chrono::Duration::minutes(minutes)
83    }
84
85    /// 增加小时
86    pub fn add_hours(datetime: DateTime<Local>, hours: i64) -> DateTime<Local> {
87        datetime + chrono::Duration::hours(hours)
88    }
89
90    /// 增加天数
91    pub fn add_days(datetime: DateTime<Local>, days: i64) -> DateTime<Local> {
92        datetime + chrono::Duration::days(days)
93    }
94
95    /// 是否为同一天
96    pub fn is_same_day(dt1: DateTime<Local>, dt2: DateTime<Local>) -> bool {
97        dt1.date_naive() == dt2.date_naive()
98    }
99
100    /// 是否为今天
101    pub fn is_today(dt: DateTime<Local>) -> bool {
102        Self::is_same_day(dt, Local::now())
103    }
104
105    /// 获取开始时间
106    pub fn start_of_day(dt: DateTime<Local>) -> DateTime<Local> {
107        dt.date_naive()
108            .and_hms_opt(0, 0, 0)
109            .unwrap()
110            .and_local_timezone(Local)
111            .unwrap()
112    }
113
114    /// 获取结束时间
115    pub fn end_of_day(dt: DateTime<Local>) -> DateTime<Local> {
116        dt.date_naive()
117            .and_hms_opt(23, 59, 59)
118            .unwrap()
119            .and_local_timezone(Local)
120            .unwrap()
121    }
122
123    /// 获取当前时间
124    #[allow(dead_code)]
125    pub fn current_datetime() -> DateTime<Utc> {
126        Utc::now()
127    }
128
129    /// 转换为本地时间
130    pub fn to_local(dt: &DateTime<Utc>) -> DateTime<Local> {
131        dt.with_timezone(&Local)
132    }
133
134    /// 序列化响应的时间格式
135    pub fn serialize_optional_datetime<S>(
136        value: &Option<DateTime<Utc>>,
137        serializer: S,
138    ) -> Result<S::Ok, S::Error>
139    where
140        S: serde::Serializer,
141    {
142        if let Some(dt) = value {
143            serializer.serialize_str(&dt.format("%Y-%m-%d %H:%M:%S").to_string())
144        } else {
145            serializer.serialize_none()
146        }
147    }
148
149    // 添加自定义反序列化函数,处理可选日期时间
150    pub fn deserialize_optional_datetime<'de, D>(
151        deserializer: D,
152    ) -> Result<Option<DateTime<Utc>>, D::Error>
153    where
154        D: serde::Deserializer<'de>,
155    {
156        let s: Option<String> = Option::deserialize(deserializer)?;
157        if let Some(s) = s {
158            if s.is_empty() {
159                return Ok(None);
160            }
161
162            // 尝试解析日期字符串
163            match chrono::NaiveDate::parse_from_str(&s, "%Y-%m-%d") {
164                Ok(date) => {
165                    // 转换为DateTime<Utc>
166                    let datetime = chrono::DateTime::<Utc>::from_naive_utc_and_offset(
167                        date.and_hms_opt(0, 0, 0).unwrap(),
168                        Utc,
169                    );
170                    Ok(Some(datetime))
171                }
172                Err(_) => {
173                    //解析失败时尝试使用带时分秒的格式解析
174                    match chrono::NaiveDateTime::parse_from_str(&s, "%Y-%m-%d %H:%M:%S") {
175                        Ok(datetime) => {
176                            // 转换为DateTime<Utc>
177                            let datetime =
178                                chrono::DateTime::<Utc>::from_naive_utc_and_offset(datetime, Utc);
179                            Ok(Some(datetime))
180                        }
181                        Err(_) => Err(serde::de::Error::custom("无法解析日期时间字符串")),
182                    }
183                }
184            }
185        } else {
186            Ok(None)
187        }
188    }
189
190    /// 格式化时间间隔
191    pub fn format_duration(duration: std::time::Duration) -> String {
192        let years = duration.as_secs() / 3600 / 24 / 365;
193        let months = (duration.as_secs() % (3600 * 24 * 365)) / (3600 * 24 * 30);
194        let days = (duration.as_secs() % (3600 * 24 * 365)) / (3600 * 24);
195        let hours = (duration.as_secs() % (3600 * 24)) / 3600;
196        let minutes = (duration.as_secs() % 3600) / 60;
197        let seconds = duration.as_secs() % 60;
198        if years > 0 {
199            format!(
200                "{}年{}月{}日 {}小时{}分钟{}秒",
201                years, months, days, hours, minutes, seconds
202            )
203        } else if months > 0 {
204            format!(
205                "{}月{}日 {}小时{}分钟{}秒",
206                months, days, hours, minutes, seconds
207            )
208        } else if days > 0 {
209            format!("{}日 {}小时{}分钟{}秒", days, hours, minutes, seconds)
210        } else {
211            format!("{}小时{}分钟{}秒", hours, minutes, seconds)
212        }
213    }
214}