use chrono::{DateTime as ChronoDateTime, TimeZone, Utc};
pub type DateTime = ChronoDateTime<Utc>;
pub fn unix_epoch() -> DateTime {
Utc.timestamp_opt(0, 0)
.single()
.expect("unix epoch timestamp is always valid")
}
pub fn from_unix_timestamp_ms(timestamp_ms: i64) -> DateTime {
Utc.timestamp_millis_opt(timestamp_ms)
.single()
.unwrap_or_else(unix_epoch)
}
pub struct DateTimeUtcAsUnixMillis;
impl rkyv::with::ArchiveWith<DateTime> for DateTimeUtcAsUnixMillis {
type Archived = rkyv::primitive::ArchivedI64;
type Resolver = ();
fn resolve_with(field: &DateTime, _: Self::Resolver, out: rkyv::place::Place<Self::Archived>) {
out.write(rkyv::primitive::ArchivedI64::from_native(
field.timestamp_millis(),
));
}
}
impl<S: rkyv::rancor::Fallible + ?Sized> rkyv::with::SerializeWith<DateTime, S>
for DateTimeUtcAsUnixMillis
{
fn serialize_with(_: &DateTime, _: &mut S) -> Result<Self::Resolver, S::Error> {
Ok(())
}
}
impl<D: rkyv::rancor::Fallible + ?Sized>
rkyv::with::DeserializeWith<rkyv::primitive::ArchivedI64, DateTime, D>
for DateTimeUtcAsUnixMillis
{
fn deserialize_with(
field: &rkyv::primitive::ArchivedI64,
_: &mut D,
) -> Result<DateTime, D::Error> {
let timestamp_ms = field.to_native();
Ok(Utc
.timestamp_millis_opt(timestamp_ms)
.single()
.expect("archived unix millis must be a valid chrono timestamp"))
}
}