1use std::str::FromStr;
16
17use chrono::{LocalResult, NaiveDateTime, TimeZone};
18use chrono_tz::Tz;
19
20use crate::timezone::get_timezone;
21use crate::Timezone;
22
23pub fn format_utc_datetime(utc: &NaiveDateTime, pattern: &str) -> String {
24 match get_timezone(None) {
25 crate::Timezone::Offset(offset) => {
26 offset.from_utc_datetime(utc).format(pattern).to_string()
27 }
28 crate::Timezone::Named(tz) => tz.from_utc_datetime(utc).format(pattern).to_string(),
29 }
30}
31
32pub fn datetime_to_utc(
34 datetime: &NaiveDateTime,
35 timezone: &Timezone,
36) -> LocalResult<NaiveDateTime> {
37 match timezone {
38 crate::Timezone::Offset(offset) => {
39 offset.from_local_datetime(datetime).map(|x| x.naive_utc())
40 }
41 crate::Timezone::Named(tz) => tz.from_local_datetime(datetime).map(|x| x.naive_utc()),
42 }
43}
44
45pub fn find_tz_from_env() -> Option<Tz> {
46 std::env::var("TZ")
51 .ok()
52 .and_then(|tz| Tz::from_str(&tz).ok())
53}
54
55pub fn current_time_millis() -> i64 {
57 chrono::Utc::now().timestamp_millis()
58}
59
60pub fn current_time_rfc3339() -> String {
62 chrono::Utc::now().to_rfc3339()
63}
64
65pub fn yesterday_rfc3339() -> String {
67 let now = chrono::Utc::now();
68 let day_before = now
69 - chrono::Duration::try_days(1).unwrap_or_else(|| {
70 panic!("now time ('{now}') is too early to calculate the day before")
71 });
72 day_before.to_rfc3339()
73}
74
75pub(crate) fn div_ceil(this: i64, rhs: i64) -> i64 {
77 let d = this / rhs;
78 let r = this % rhs;
79 if r > 0 && rhs > 0 {
80 d + 1
81 } else {
82 d
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use std::time::{self, SystemTime};
89
90 use chrono::{Datelike, TimeZone, Timelike};
91
92 use super::*;
93
94 #[test]
95 fn test_current_time_millis() {
96 let now = current_time_millis();
97
98 let millis_from_std = SystemTime::now()
99 .duration_since(time::UNIX_EPOCH)
100 .unwrap()
101 .as_millis() as i64;
102 let datetime_now = chrono::Utc.timestamp_millis_opt(now).unwrap();
103 let datetime_std = chrono::Utc.timestamp_millis_opt(millis_from_std).unwrap();
104
105 assert_eq!(datetime_std.year(), datetime_now.year());
106 assert_eq!(datetime_std.month(), datetime_now.month());
107 assert_eq!(datetime_std.day(), datetime_now.day());
108 assert_eq!(datetime_std.hour(), datetime_now.hour());
109 assert_eq!(datetime_std.minute(), datetime_now.minute());
110 }
111
112 #[test]
113 fn test_div_ceil() {
114 let v0 = 9223372036854676001;
115 assert_eq!(9223372036854677, div_ceil(v0, 1000));
116 }
117}