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