use std::fmt;
use std::time::Duration;
use std::time::UNIX_EPOCH;
use chrono::DateTime;
use chrono::Utc;
pub struct DisplayUnixTimeStamp {
duration: Option<Duration>,
in_millis: bool,
with_timezone: bool,
}
impl fmt::Display for DisplayUnixTimeStamp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let duration = match self.duration {
Some(d) => d,
None => return write!(f, "None"),
};
let system_time = UNIX_EPOCH + duration;
let datetime: DateTime<Utc> = system_time.into();
let fmt = if self.in_millis {
if self.with_timezone {
"%Y-%m-%dT%H:%M:%S%.3fZ%z"
} else {
"%Y-%m-%dT%H:%M:%S%.3f"
}
} else if self.with_timezone {
"%Y-%m-%dT%H:%M:%S%.6fZ%z"
} else {
"%Y-%m-%dT%H:%M:%S%.6f"
};
write!(f, "{}", datetime.format(fmt))
}
}
impl DisplayUnixTimeStamp {
pub fn new(duration: Option<Duration>) -> Self {
Self {
duration,
in_millis: false,
with_timezone: true,
}
}
pub fn in_millis(self, in_millis: bool) -> Self {
Self { in_millis, ..self }
}
pub fn with_timezone(self, with_timezone: bool) -> Self {
Self {
with_timezone,
..self
}
}
}
pub trait DisplayUnixTimeStampExt {
fn display_unix_timestamp(&self) -> DisplayUnixTimeStamp;
fn display_unix_timestamp_short(&self) -> DisplayUnixTimeStamp {
self.display_unix_timestamp()
.in_millis(true)
.with_timezone(false)
}
}
impl DisplayUnixTimeStampExt for Duration {
fn display_unix_timestamp(&self) -> DisplayUnixTimeStamp {
DisplayUnixTimeStamp::new(Some(*self))
}
}
impl DisplayUnixTimeStampExt for Option<Duration> {
fn display_unix_timestamp(&self) -> DisplayUnixTimeStamp {
DisplayUnixTimeStamp::new(*self)
}
}
#[cfg(test)]
mod tests {
use std::time::Duration;
use super::*;
#[test]
fn test_display_unix_epoch() {
let epoch = Duration::from_millis(0);
let display = epoch.display_unix_timestamp();
assert_eq!(format!("{}", display), "1970-01-01T00:00:00.000000Z+0000");
let epoch = Duration::from_millis(1723102819023);
let display = epoch.display_unix_timestamp();
assert_eq!(format!("{}", display), "2024-08-08T07:40:19.023000Z+0000");
let display = epoch.display_unix_timestamp_short();
assert_eq!(format!("{}", display), "2024-08-08T07:40:19.023");
let display = epoch.display_unix_timestamp().in_millis(true);
assert_eq!(format!("{}", display), "2024-08-08T07:40:19.023Z+0000");
let display = epoch.display_unix_timestamp().with_timezone(false);
assert_eq!(format!("{}", display), "2024-08-08T07:40:19.023000");
let some = Some(Duration::from_millis(1723102819023));
assert_eq!(
some.display_unix_timestamp().to_string(),
"2024-08-08T07:40:19.023000Z+0000"
);
assert_eq!(
some.display_unix_timestamp_short().to_string(),
"2024-08-08T07:40:19.023"
);
let none: Option<Duration> = None;
assert_eq!(none.display_unix_timestamp().to_string(), "None");
assert_eq!(none.display_unix_timestamp_short().to_string(), "None");
}
}