use std::{fmt::Debug, ops::Add};
use instant::SystemTime;
use serde_derive::{Deserialize, Serialize};
use time::{format_description::well_known::Rfc3339, OffsetDateTime};
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(transparent)]
pub struct MsSinceEpoch(#[serde(with = "ms_to_human")] pub i64);
impl MsSinceEpoch {
fn now() -> Self {
MsSinceEpoch(
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_millis() as i64,
)
}
}
impl Debug for MsSinceEpoch {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{:?}",
OffsetDateTime::from_unix_timestamp_nanos(self.0 as i128 * 1_000_000)
.unwrap()
.format(&Rfc3339)
.unwrap()
)
}
}
pub fn now() -> MsSinceEpoch {
MsSinceEpoch::now()
}
impl Add<i64> for MsSinceEpoch {
type Output = Self;
fn add(self, rhs: i64) -> Self::Output {
Self(self.0 + rhs)
}
}
mod ms_to_human {
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
use time::{format_description::well_known::Rfc3339, OffsetDateTime};
pub fn serialize<S>(ms: &i64, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
OffsetDateTime::from_unix_timestamp_nanos(*ms as i128 * 1_000_000)
.unwrap()
.format(&Rfc3339)
.unwrap()
.serialize(serializer)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<i64, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
let dt =
OffsetDateTime::parse(&s, &Rfc3339).map_err(|err| D::Error::custom(err.to_string()))?;
Ok((dt.unix_timestamp_nanos() / 1_000_000) as i64)
}
}