time/serde/timestamp/microseconds.rs
1//! Treat an [`OffsetDateTime`] as a [Unix timestamp] with microseconds 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 microseconds
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;
23 timestamp.serialize(serializer)
24}
25
26/// Deserialize an `OffsetDateTime` from its Unix timestamp with microseconds
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 value
34 .checked_mul(1_000)
35 .map(OffsetDateTime::from_unix_timestamp_nanos)
36 .unwrap_or_else(|| Err(ComponentRange::unconditional("timestamp")))
37 .map_err(ComponentRange::into_de_error)
38}
39
40/// Treat an `Option<OffsetDateTime>` as a [Unix timestamp] with microseconds
41/// for the purposes of serde.
42///
43/// Use this module in combination with serde's [`#[with]`][with] attribute.
44///
45/// Note: Due to [serde-rs/serde#2878], you will need to apply `#[serde(default)]` if you want a
46/// missing field to deserialize as `None`.
47///
48/// When deserializing, the offset is assumed to be UTC.
49///
50/// [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time
51/// [with]: https://serde.rs/field-attrs.html#with
52/// [serde-rs/serde#2878]: https://github.com/serde-rs/serde/issues/2878
53pub mod option {
54 use super::*;
55
56 /// Serialize an `Option<OffsetDateTime>` as its Unix timestamp with microseconds
57 #[inline]
58 pub fn serialize<S>(option: &Option<OffsetDateTime>, serializer: S) -> Result<S::Ok, S::Error>
59 where
60 S: Serializer,
61 {
62 option
63 .map(|timestamp| timestamp.unix_timestamp_nanos() / 1_000)
64 .serialize(serializer)
65 }
66
67 /// Deserialize an `Option<OffsetDateTime>` from its Unix timestamp with microseconds
68 #[inline]
69 pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<OffsetDateTime>, D::Error>
70 where
71 D: Deserializer<'a>,
72 {
73 Option::deserialize(deserializer)?
74 .map(|value: i128| {
75 value
76 .checked_mul(1_000)
77 .map(OffsetDateTime::from_unix_timestamp_nanos)
78 .unwrap_or_else(|| Err(ComponentRange::unconditional("timestamp")))
79 })
80 .transpose()
81 .map_err(ComponentRange::into_de_error)
82 }
83}