use std::str::FromStr;
use chrono::{LocalResult, NaiveDateTime, TimeZone};
use chrono_tz::Tz;
use crate::timezone::get_timezone;
use crate::Timezone;
pub fn format_utc_datetime(utc: &NaiveDateTime, pattern: &str) -> String {
match get_timezone(None) {
crate::Timezone::Offset(offset) => {
offset.from_utc_datetime(utc).format(pattern).to_string()
}
crate::Timezone::Named(tz) => tz.from_utc_datetime(utc).format(pattern).to_string(),
}
}
pub fn datetime_to_utc(
datetime: &NaiveDateTime,
timezone: &Timezone,
) -> LocalResult<NaiveDateTime> {
match timezone {
crate::Timezone::Offset(offset) => {
offset.from_local_datetime(datetime).map(|x| x.naive_utc())
}
crate::Timezone::Named(tz) => tz.from_local_datetime(datetime).map(|x| x.naive_utc()),
}
}
pub fn find_tz_from_env() -> Option<Tz> {
std::env::var("TZ")
.ok()
.and_then(|tz| Tz::from_str(&tz).ok())
}
pub fn current_time_millis() -> i64 {
chrono::Utc::now().timestamp_millis()
}
pub fn current_time_rfc3339() -> String {
chrono::Utc::now().to_rfc3339()
}
pub fn yesterday_rfc3339() -> String {
let now = chrono::Utc::now();
let day_before = now
- chrono::Duration::try_days(1).unwrap_or_else(|| {
panic!("now time ('{now}') is too early to calculate the day before")
});
day_before.to_rfc3339()
}
pub(crate) fn div_ceil(this: i64, rhs: i64) -> i64 {
let d = this / rhs;
let r = this % rhs;
if r > 0 && rhs > 0 {
d + 1
} else {
d
}
}
#[cfg(test)]
mod tests {
use std::time::{self, SystemTime};
use chrono::{Datelike, TimeZone, Timelike};
use super::*;
#[test]
fn test_current_time_millis() {
let now = current_time_millis();
let millis_from_std = SystemTime::now()
.duration_since(time::UNIX_EPOCH)
.unwrap()
.as_millis() as i64;
let datetime_now = chrono::Utc.timestamp_millis_opt(now).unwrap();
let datetime_std = chrono::Utc.timestamp_millis_opt(millis_from_std).unwrap();
assert_eq!(datetime_std.year(), datetime_now.year());
assert_eq!(datetime_std.month(), datetime_now.month());
assert_eq!(datetime_std.day(), datetime_now.day());
assert_eq!(datetime_std.hour(), datetime_now.hour());
assert_eq!(datetime_std.minute(), datetime_now.minute());
}
#[test]
fn test_div_ceil() {
let v0 = 9223372036854676001;
assert_eq!(9223372036854677, div_ceil(v0, 1000));
}
}