//! Treat an [`OffsetDateTime`] as a [Unix timestamp] with milliseconds for //! the purposes of serde. //! //! Use this module in combination with serde's [`#[with]`][with] attribute. //! //! When deserializing, the offset is assumed to be UTC. //! //! [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time //! [with]: https://serde.rs/field-attrs.html#with use num_conv::prelude::*; use serde_core::{Deserialize, Deserializer, Serialize, Serializer}; use crate::OffsetDateTime; use crate::error::ComponentRange; /// Serialize an `OffsetDateTime` as its Unix timestamp with milliseconds #[inline] pub fn serialize(datetime: &OffsetDateTime, serializer: S) -> Result where S: Serializer, { let timestamp = (datetime.unix_timestamp_nanos() / 1_000_000).truncate::(); timestamp.serialize(serializer) } /// Deserialize an `OffsetDateTime` from its Unix timestamp with milliseconds #[inline] pub fn deserialize<'a, D>(deserializer: D) -> Result where D: Deserializer<'a>, { let value: i64 = <_>::deserialize(deserializer)?; OffsetDateTime::from_unix_timestamp_nanos(value.extend::() * 1_000_000) .map_err(ComponentRange::into_de_error) } /// Treat an `Option` as a [Unix timestamp] with milliseconds /// for the purposes of serde. /// /// Use this module in combination with serde's [`#[with]`][with] attribute. /// /// Note: Due to [serde-rs/serde#2878], you will need to apply `#[serde(default)]` if you want a /// missing field to deserialize as `None`. /// /// When deserializing, the offset is assumed to be UTC. /// /// [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time /// [with]: https://serde.rs/field-attrs.html#with /// [serde-rs/serde#2878]: https://github.com/serde-rs/serde/issues/2878 pub mod option { use super::*; /// Serialize an `Option` as its Unix timestamp with milliseconds #[inline] pub fn serialize(option: &Option, serializer: S) -> Result where S: Serializer, { option .map(|timestamp| (timestamp.unix_timestamp_nanos() / 1_000_000).truncate::()) .serialize(serializer) } /// Deserialize an `Option` from its Unix timestamp with milliseconds #[inline] pub fn deserialize<'a, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'a>, { Option::deserialize(deserializer)? .map(|value: i64| { OffsetDateTime::from_unix_timestamp_nanos(value.extend::() * 1_000_000) }) .transpose() .map_err(ComponentRange::into_de_error) } }