use chrono::{DateTime, TimeZone, Utc};
use serde::{Deserialize, Deserializer, Serializer};
pub mod option {
use super::{DateTime, Deserialize, Deserializer, Serializer, TimeZone, Utc};
pub fn serialize<S: Serializer>(dt: &Option<DateTime<Utc>>, s: S) -> Result<S::Ok, S::Error> {
match dt {
Some(d) => {
#[allow(clippy::cast_precision_loss)]
let secs = d.timestamp() as f64 + f64::from(d.timestamp_subsec_millis()) / 1000.0;
s.serialize_f64(secs)
}
None => s.serialize_none(),
}
}
pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Option<DateTime<Utc>>, D::Error> {
let opt: Option<f64> = Option::deserialize(d)?;
match opt {
Some(secs) => {
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
let whole = secs.trunc() as i64;
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
let nanos = (secs.fract() * 1_000_000_000.0) as u32;
Utc.timestamp_opt(whole, nanos)
.single()
.ok_or_else(|| serde::de::Error::custom("invalid epoch timestamp"))
.map(Some)
}
None => Ok(None),
}
}
}