next_web_utils/datetime/
datetime_util.rs1use chrono::{DateTime, Datelike, Duration, Local, NaiveDate, NaiveDateTime, TimeZone, Utc, FixedOffset};
2
3pub struct DateTimeUtil;
5
6impl DateTimeUtil {
7 pub fn now() -> String {
9 let now: DateTime<Local> = Local::now();
10 now.format("%Y-%m-%d %H:%M:%S%.3f").to_string()
11 }
12
13 pub fn timestamp() -> i64 {
15 Local::now().timestamp_millis()
16 }
17
18 pub fn date() -> String {
20 Local::now().format("%Y-%m-%d").to_string()
21 }
22
23 pub fn time() -> String {
25 Local::now().format("%H:%M:%S").to_string()
26 }
27
28 pub fn format_now(fmt: &str) -> String {
30 Local::now().format(fmt).to_string()
31 }
32
33 pub fn from_timestamp(timestamp: i64, fmt: &str) -> String {
35 let dt = Local.timestamp_opt(timestamp, 0).unwrap();
36 dt.format(fmt).to_string()
37 }
38
39 pub fn parse(datetime_str: &str, fmt: &str) -> Option<NaiveDateTime> {
41 NaiveDateTime::parse_from_str(datetime_str, fmt).ok()
42 }
43
44 pub fn is_same_day(dt1: &NaiveDateTime, dt2: &NaiveDateTime) -> bool {
46 dt1.date() == dt2.date()
47 }
48
49 pub fn add_days(dt: &NaiveDateTime, days: i64) -> NaiveDateTime {
51 *dt + Duration::days(days)
52 }
53
54 pub fn add_hours(dt: &NaiveDateTime, hours: i64) -> NaiveDateTime {
56 *dt + Duration::hours(hours)
57 }
58
59 pub fn add_minutes(dt: &NaiveDateTime, minutes: i64) -> NaiveDateTime {
61 *dt + Duration::minutes(minutes)
62 }
63
64 pub fn days_between(dt1: &NaiveDateTime, dt2: &NaiveDateTime) -> i64 {
66 let duration = *dt2 - *dt1;
67 duration.num_days()
68 }
69
70 pub fn first_day_of_month(year: i32, month: u32) -> Option<NaiveDate> {
72 NaiveDate::from_ymd_opt(year, month, 1)
73 }
74
75 pub fn last_day_of_month(year: i32, month: u32) -> Option<NaiveDate> {
77 let first_of_next_month = if month == 12 {
78 NaiveDate::from_ymd_opt(year + 1, 1, 1)
79 } else {
80 NaiveDate::from_ymd_opt(year, month + 1, 1)
81 };
82
83 first_of_next_month.map(|d| d.pred_opt().unwrap())
84 }
85
86 pub fn is_weekday(dt: &NaiveDateTime) -> bool {
88 let weekday = dt.weekday().number_from_monday();
89 weekday >= 1 && weekday <= 5
90 }
91
92 pub fn is_weekend(dt: &NaiveDateTime) -> bool {
94 let weekday = dt.weekday().number_from_monday();
95 weekday == 6 || weekday == 7
96 }
97
98 pub fn to_utc(dt: DateTime<Local>) -> DateTime<Utc> {
100 dt.with_timezone(&Utc)
101 }
102
103 pub fn change_timezone(dt: &DateTime<Utc>, hours: i32) -> DateTime<FixedOffset> {
105 let offset = FixedOffset::east_opt(hours * 3600).unwrap();
106 dt.with_timezone(&offset)
107 }
108
109 pub fn get_quarter(dt: &NaiveDateTime) -> u32 {
111 (dt.month() - 1) / 3 + 1
112 }
113
114 pub fn calculate_age(birth_date: &NaiveDate) -> u32 {
116 let today = Local::now().naive_local().date();
117 let age = today.year() - birth_date.year();
118
119 if today.month() < birth_date.month() ||
120 (today.month() == birth_date.month() && today.day() < birth_date.day()) {
121 return (age - 1) as u32;
122 }
123
124 age as u32
125 }
126}