time/serde/
iso8601.rs

1//! Use the well-known [ISO 8601 format] when serializing and deserializing an [`OffsetDateTime`].
2//!
3//! Use this module in combination with serde's [`#[with]`][with] attribute.
4//!
5//! [ISO 8601 format]: https://www.iso.org/iso-8601-date-and-time-format.html
6//! [with]: https://serde.rs/field-attrs.html#with
7
8#[cfg(feature = "parsing")]
9use core::marker::PhantomData;
10
11#[cfg(feature = "parsing")]
12use serde_core::Deserializer;
13#[cfg(feature = "formatting")]
14use serde_core::ser::Error as _;
15#[cfg(feature = "formatting")]
16use serde_core::{Serialize, Serializer};
17
18#[cfg(feature = "parsing")]
19use super::Visitor;
20use crate::OffsetDateTime;
21use crate::format_description::well_known::Iso8601;
22use crate::format_description::well_known::iso8601::{Config, EncodedConfig};
23
24/// The configuration of ISO 8601 used for serde implementations.
25pub(crate) const SERDE_CONFIG: EncodedConfig =
26    Config::DEFAULT.set_year_is_six_digits(true).encode();
27
28/// Serialize an [`OffsetDateTime`] using the well-known ISO 8601 format.
29#[cfg(feature = "formatting")]
30#[inline]
31pub fn serialize<S>(datetime: &OffsetDateTime, serializer: S) -> Result<S::Ok, S::Error>
32where
33    S: Serializer,
34{
35    datetime
36        .format(&Iso8601::<SERDE_CONFIG>)
37        .map_err(S::Error::custom)?
38        .serialize(serializer)
39}
40
41/// Deserialize an [`OffsetDateTime`] from its ISO 8601 representation.
42#[cfg(feature = "parsing")]
43#[inline]
44pub fn deserialize<'a, D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
45where
46    D: Deserializer<'a>,
47{
48    deserializer.deserialize_str(Visitor::<Iso8601<SERDE_CONFIG>>(PhantomData))
49}
50
51/// Use the well-known ISO 8601 format when serializing and deserializing an
52/// [`Option<OffsetDateTime>`].
53///
54/// Use this module in combination with serde's [`#[with]`][with] attribute.
55///
56/// Note: Due to [serde-rs/serde#2878], you will need to apply `#[serde(default)]` if you want a
57/// missing field to deserialize as `None`.
58///
59/// [ISO 8601 format]: https://www.iso.org/iso-8601-date-and-time-format.html
60/// [with]: https://serde.rs/field-attrs.html#with
61/// [serde-rs/serde#2878]: https://github.com/serde-rs/serde/issues/2878
62pub mod option {
63    use super::*;
64
65    /// Serialize an [`Option<OffsetDateTime>`] using the well-known ISO 8601 format.
66    #[cfg(feature = "formatting")]
67    #[inline]
68    pub fn serialize<S>(option: &Option<OffsetDateTime>, serializer: S) -> Result<S::Ok, S::Error>
69    where
70        S: Serializer,
71    {
72        option
73            .map(|odt| odt.format(&Iso8601::<SERDE_CONFIG>))
74            .transpose()
75            .map_err(S::Error::custom)?
76            .serialize(serializer)
77    }
78
79    /// Deserialize an [`Option<OffsetDateTime>`] from its ISO 8601 representation.
80    #[cfg(feature = "parsing")]
81    #[inline]
82    pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<OffsetDateTime>, D::Error>
83    where
84        D: Deserializer<'a>,
85    {
86        deserializer.deserialize_option(Visitor::<Option<Iso8601<SERDE_CONFIG>>>(PhantomData))
87    }
88}