use std::num::NonZeroU8;
use ruma::MilliSecondsSinceUnixEpoch;
use time::{
format_description::well_known::{iso8601, Iso8601},
OffsetDateTime,
};
#[cfg(test)]
pub(crate) fn json_convert<T, U>(value: &T) -> serde_json::Result<U>
where
T: serde::Serialize,
U: serde::de::DeserializeOwned,
{
let json = serde_json::to_string(value)?;
serde_json::from_str(&json)
}
const ISO8601_WITH_MILLIS: iso8601::EncodedConfig = iso8601::Config::DEFAULT
.set_time_precision(iso8601::TimePrecision::Second { decimal_digits: NonZeroU8::new(3) })
.encode();
pub fn timestamp_to_iso8601(ts: MilliSecondsSinceUnixEpoch) -> Option<String> {
let nanos_since_epoch = i128::from(ts.get()) * 1_000_000;
let dt = OffsetDateTime::from_unix_timestamp_nanos(nanos_since_epoch).ok()?;
Some(dt.format(&Iso8601::<ISO8601_WITH_MILLIS>).unwrap())
}
#[cfg(test)]
pub(crate) mod tests {
use ruma::{MilliSecondsSinceUnixEpoch, UInt};
use super::timestamp_to_iso8601;
#[test]
fn test_timestamp_to_iso8601() {
assert_eq!(
timestamp_to_iso8601(MilliSecondsSinceUnixEpoch(UInt::new_saturating(0))),
Some("1970-01-01T00:00:00.000Z".to_owned())
);
assert_eq!(
timestamp_to_iso8601(MilliSecondsSinceUnixEpoch(UInt::new_saturating(1709657033012))),
Some("2024-03-05T16:43:53.012Z".to_owned())
);
assert_eq!(timestamp_to_iso8601(MilliSecondsSinceUnixEpoch(UInt::MAX)), None);
}
}