time/serde/timestamp/
milliseconds_i64.rs

1//! Treat an [`OffsetDateTime`] as a [Unix timestamp] with milliseconds for
2//! the purposes of serde.
3//!
4//! Use this module in combination with serde's [`#[with]`][with] attribute.
5//!
6//! When deserializing, the offset is assumed to be UTC.
7//!
8//! [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time
9//! [with]: https://serde.rs/field-attrs.html#with
10
11use num_conv::prelude::*;
12use serde_core::{Deserialize, Deserializer, Serialize, Serializer};
13
14use crate::OffsetDateTime;
15use crate::error::ComponentRange;
16
17/// Serialize an `OffsetDateTime` as its Unix timestamp with milliseconds
18#[inline]
19pub fn serialize<S>(datetime: &OffsetDateTime, serializer: S) -> Result<S::Ok, S::Error>
20where
21    S: Serializer,
22{
23    let timestamp = (datetime.unix_timestamp_nanos() / 1_000_000).truncate::<i64>();
24    timestamp.serialize(serializer)
25}
26
27/// Deserialize an `OffsetDateTime` from its Unix timestamp with milliseconds
28#[inline]
29pub fn deserialize<'a, D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
30where
31    D: Deserializer<'a>,
32{
33    let value: i64 = <_>::deserialize(deserializer)?;
34    OffsetDateTime::from_unix_timestamp_nanos(value.extend::<i128>() * 1_000_000)
35        .map_err(ComponentRange::into_de_error)
36}
37
38/// Treat an `Option<OffsetDateTime>` as a [Unix timestamp] with milliseconds
39/// for the purposes of serde.
40///
41/// Use this module in combination with serde's [`#[with]`][with] attribute.
42///
43/// Note: Due to [serde-rs/serde#2878], you will need to apply `#[serde(default)]` if you want a
44/// missing field to deserialize as `None`.
45///
46/// When deserializing, the offset is assumed to be UTC.
47///
48/// [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time
49/// [with]: https://serde.rs/field-attrs.html#with
50/// [serde-rs/serde#2878]: https://github.com/serde-rs/serde/issues/2878
51pub mod option {
52    use super::*;
53
54    /// Serialize an `Option<OffsetDateTime>` as its Unix timestamp with milliseconds
55    #[inline]
56    pub fn serialize<S>(option: &Option<OffsetDateTime>, serializer: S) -> Result<S::Ok, S::Error>
57    where
58        S: Serializer,
59    {
60        option
61            .map(|timestamp| (timestamp.unix_timestamp_nanos() / 1_000_000).truncate::<i64>())
62            .serialize(serializer)
63    }
64
65    /// Deserialize an `Option<OffsetDateTime>` from its Unix timestamp with milliseconds
66    #[inline]
67    pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<OffsetDateTime>, D::Error>
68    where
69        D: Deserializer<'a>,
70    {
71        Option::deserialize(deserializer)?
72            .map(|value: i64| {
73                OffsetDateTime::from_unix_timestamp_nanos(value.extend::<i128>() * 1_000_000)
74            })
75            .transpose()
76            .map_err(ComponentRange::into_de_error)
77    }
78}