use core::fmt;
use std::fmt::Display;
use std::fmt::Formatter;
use chrono::DateTime;
use chrono::TimeDelta;
use chrono::Utc;
use chrono::format::DelayedFormat;
use chrono::format::StrftimeItems;
use crate::Duration;
use crate::Time;
use crate::TimeWindow;
impl Time {
#[must_use]
pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> {
let secs = self.0 / 1000;
let nanos = (self.0 % 1000) * 1_000_000;
#[expect(
clippy::cast_possible_truncation,
reason = "casting to u32 is safe here because it is guaranteed that the value is in 0..1_000_000_000"
)]
let nanos = if nanos.is_negative() {
1_000_000_000 - nanos.unsigned_abs()
} else {
nanos.unsigned_abs()
} as u32;
let t = DateTime::from_timestamp(secs, nanos);
match t {
None => DelayedFormat::new(None, None, StrftimeItems::new("∞")),
Some(v) => v.format(fmt),
}
}
pub fn parse_from_rfc3339(s: &str) -> Result<Time, chrono::ParseError> {
DateTime::parse_from_rfc3339(s)
.map(|chrono_datetime| Time::millis(chrono_datetime.timestamp_millis()))
}
#[must_use]
pub fn to_rfc3339(self) -> String {
self.format("%Y-%m-%dT%H:%M:%S+00:00").to_string()
}
}
impl Display for Time {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let rfc3339_string = self.to_rfc3339();
write!(f, "{rfc3339_string}")
}
}
impl Display for TimeWindow {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "[{}, {}]", self.start, self.end)
}
}
impl From<DateTime<Utc>> for Time {
fn from(dt: DateTime<Utc>) -> Self {
Time::millis(dt.timestamp_millis())
}
}
impl From<TimeDelta> for Duration {
fn from(td: TimeDelta) -> Self {
Duration::millis(td.num_milliseconds())
}
}