Skip to main content

time/serde/
mod.rs

1//! Differential formats for serde.
2// This also includes the serde implementations for all types. This doesn't need to be externally
3// documented, though.
4
5// Types with guaranteed stable serde representations. Strings are avoided to allow for optimal
6// representations in various binary forms.
7
8/// Consume the next item in a sequence.
9macro_rules! item {
10    ($seq:expr, $name:literal) => {
11        $seq.next_element()?
12            .ok_or_else(|| <A::Error as serde_core::de::Error>::custom(concat!("expected ", $name)))
13    };
14}
15
16#[cfg(any(feature = "formatting", feature = "parsing"))]
17pub mod iso8601;
18#[cfg(any(feature = "formatting", feature = "parsing"))]
19pub mod rfc2822;
20#[cfg(any(feature = "formatting", feature = "parsing"))]
21pub mod rfc3339;
22pub mod timestamp;
23mod visitor;
24
25#[cfg(feature = "serde-human-readable")]
26use alloc::string::ToString;
27use core::marker::PhantomData;
28
29#[cfg(feature = "serde-human-readable")]
30use serde_core::ser::Error as _;
31use serde_core::{Deserialize, Deserializer, Serialize, Serializer};
32/// Generate a custom serializer and deserializer from a format string or an existing format.
33///
34/// The format description syntax accepted by this macro is the same as
35/// [`format_description::parse()`], which can be found in [the
36/// book][format-description-syntax].
37///
38/// [format-description-syntax]: https://time-rs.github.io/book/api/format-description.html
39///
40/// # Syntax
41///
42/// **It is recommended to use version 3.** For backwards compatibility, this macro defaults to
43/// version 1. To use version 2 or version 3, you can specify the version as the first
44/// argument: `serde::format_description!(version = 2, mod_name, Date, FORMAT)`.
45///
46/// For versions 1 and 2, this macro is invoked as `serde::format_description!(mod_name, Date,
47/// FORMAT)` where `FORMAT` is either a `"<format string>"` or something that implements
48#[cfg_attr(
49    all(feature = "formatting", feature = "parsing"),
50    doc = "[`Formattable`](crate::formatting::Formattable) and \
51           [`Parsable`](crate::parsing::Parsable)."
52)]
53#[cfg_attr(
54    all(feature = "formatting", not(feature = "parsing")),
55    doc = "[`Formattable`](crate::formatting::Formattable)."
56)]
57#[cfg_attr(
58    all(not(feature = "formatting"), feature = "parsing"),
59    doc = "[`Parsable`](crate::parsing::Parsable)."
60)]
61/// This puts a module named `mod_name` in the current scope that can be used to format `Date`
62/// structs. A submodule (`mod_name::option`) is also generated for `Option<Date>`. Both
63/// modules are only visible in the current scope by default. To increase visibility, you can
64/// specify `pub`, `pub(crate)`, or similar before the module name:
65/// `serde::format_description!(pub mod_name, Date, FORMAT)`.
66///
67/// For version 3, this macro is invoked as `serde::format_description!(mod mod_name [Date] =
68/// FORMAT)`. As with versions 1 and 2, visibility can be specified before the `mod` keyword.
69/// The type being formatted and/or parsed must be in scope, as the macro will not import it
70/// for you. Note: the `mod` keyword indicates that this is version 3 of the macro; specifying
71/// `version = 3` is accepted but unnecessary.
72///
73/// # Semantics
74///
75/// The returned `Option` will contain a deserialized value if present and `None` if the field
76/// is present but the value is `null` (or the equivalent in other formats). To return `None`
77/// when the field is not present, you should use `#[serde(default)]` on the field.
78///
79/// Note: Due to [serde-rs/serde#2878](https://github.com/serde-rs/serde#2878), you will need to
80/// apply `#[serde(default)]` if you want a missing field to deserialize as `None`.
81///
82/// # Examples
83///
84/// Using a format string:
85///
86/// ```rust,no_run
87/// # use time::OffsetDateTime;
88#[cfg_attr(
89    all(feature = "formatting", feature = "parsing"),
90    doc = "use ::serde::{Serialize, Deserialize};"
91)]
92#[cfg_attr(
93    all(feature = "formatting", not(feature = "parsing")),
94    doc = "use ::serde::Serialize;"
95)]
96#[cfg_attr(
97    all(not(feature = "formatting"), feature = "parsing"),
98    doc = "use ::serde::Deserialize;"
99)]
100/// use time::serde;
101///
102/// // Makes a module `mod my_format { ... }`.
103/// serde::format_description!(my_format, OffsetDateTime, "hour=[hour], minute=[minute]");
104///
105/// # #[allow(dead_code)]
106#[cfg_attr(
107    all(feature = "formatting", feature = "parsing"),
108    doc = "#[derive(Serialize, Deserialize)]"
109)]
110#[cfg_attr(
111    all(feature = "formatting", not(feature = "parsing")),
112    doc = "#[derive(Serialize)]"
113)]
114#[cfg_attr(
115    all(not(feature = "formatting"), feature = "parsing"),
116    doc = "#[derive(Deserialize)]"
117)]
118/// struct SerializesWithCustom {
119///     #[serde(with = "my_format")]
120///     dt: OffsetDateTime,
121///     #[serde(with = "my_format::option", default)]
122///     maybe_dt: Option<OffsetDateTime>,
123/// }
124/// ```
125/// 
126/// Define the format separately to be used in multiple places:
127/// ```rust,no_run
128/// # use time::OffsetDateTime;
129#[cfg_attr(
130    all(feature = "formatting", feature = "parsing"),
131    doc = "use ::serde::{Serialize, Deserialize};"
132)]
133#[cfg_attr(
134    all(feature = "formatting", not(feature = "parsing")),
135    doc = "use ::serde::Serialize;"
136)]
137#[cfg_attr(
138    all(not(feature = "formatting"), feature = "parsing"),
139    doc = "use ::serde::Deserialize;"
140)]
141/// use time::serde;
142/// use time::format_description::StaticFormatDescription;
143///
144/// const DATE_TIME_FORMAT: StaticFormatDescription = time::macros::format_description!(
145///     "hour=[hour], minute=[minute]"
146/// );
147///
148/// // Makes a module `mod my_format { ... }`.
149/// serde::format_description!(my_format, OffsetDateTime, DATE_TIME_FORMAT);
150///
151/// # #[allow(dead_code)]
152#[cfg_attr(
153    all(feature = "formatting", feature = "parsing"),
154    doc = "#[derive(Serialize, Deserialize)]"
155)]
156#[cfg_attr(
157    all(feature = "formatting", not(feature = "parsing")),
158    doc = "#[derive(Serialize)]"
159)]
160#[cfg_attr(
161    all(not(feature = "formatting"), feature = "parsing"),
162    doc = "#[derive(Deserialize)]"
163)]
164/// struct SerializesWithCustom {
165///     #[serde(with = "my_format")]
166///     dt: OffsetDateTime,
167///     #[serde(with = "my_format::option", default)]
168///     maybe_dt: Option<OffsetDateTime>,
169/// }
170///
171/// fn main() {
172///     # #[expect(unused_variables)]
173///     let str_ts = OffsetDateTime::now_utc().format(DATE_TIME_FORMAT).unwrap();
174/// }
175/// ```
176/// 
177/// Customize the configuration of ISO 8601 formatting/parsing:
178/// ```rust,no_run
179/// # use time::OffsetDateTime;
180#[cfg_attr(
181    all(feature = "formatting", feature = "parsing"),
182    doc = "use ::serde::{Serialize, Deserialize};"
183)]
184#[cfg_attr(
185    all(feature = "formatting", not(feature = "parsing")),
186    doc = "use ::serde::Serialize;"
187)]
188#[cfg_attr(
189    all(not(feature = "formatting"), feature = "parsing"),
190    doc = "use ::serde::Deserialize;"
191)]
192/// use time::serde;
193/// use time::format_description::well_known::{iso8601, Iso8601};
194///
195/// # #[allow(dead_code)]
196/// const CONFIG: iso8601::EncodedConfig = iso8601::Config::DEFAULT
197///     .set_year_is_six_digits(false)
198///     .encode();
199/// # #[allow(dead_code)]
200/// const FORMAT: Iso8601<CONFIG> = Iso8601::<CONFIG>;
201///
202/// // Makes a module `mod my_format { ... }`.
203/// serde::format_description!(my_format, OffsetDateTime, FORMAT);
204///
205/// # #[allow(dead_code)]
206#[cfg_attr(
207    all(feature = "formatting", feature = "parsing"),
208    doc = "#[derive(Serialize, Deserialize)]"
209)]
210#[cfg_attr(
211    all(feature = "formatting", not(feature = "parsing")),
212    doc = "#[derive(Serialize)]"
213)]
214#[cfg_attr(
215    all(not(feature = "formatting"), feature = "parsing"),
216    doc = "#[derive(Deserialize)]"
217)]
218/// struct SerializesWithCustom {
219///     #[serde(with = "my_format")]
220///     dt: OffsetDateTime,
221///     #[serde(with = "my_format::option", default)]
222///     maybe_dt: Option<OffsetDateTime>,
223/// }
224/// # fn main() {}
225/// ```
226/// 
227/// [`format_description::parse()`]: crate::format_description::parse()
228#[cfg(all(feature = "macros", any(feature = "formatting", feature = "parsing")))]
229pub use time_macros::serde_format_description as format_description;
230
231use self::visitor::Visitor;
232#[cfg(feature = "parsing")]
233use crate::format_description::__private::FormatDescriptionV3Inner;
234#[cfg(feature = "parsing")]
235use crate::format_description::{FormatDescriptionV3, modifier};
236use crate::{
237    Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, Timestamp, UtcDateTime,
238    UtcOffset, Weekday,
239};
240
241/// The format used when serializing and deserializing a human-readable `Date`.
242#[cfg(feature = "parsing")]
243const DATE_FORMAT: FormatDescriptionV3<'_> = FormatDescriptionV3Inner::BorrowedCompound(&[
244    #[cfg(feature = "large-dates")]
245    FormatDescriptionV3Inner::CalendarYearFullExtendedRange(
246        modifier::CalendarYearFullExtendedRange::default(),
247    ),
248    #[cfg(not(feature = "large-dates"))]
249    FormatDescriptionV3Inner::CalendarYearFullStandardRange(
250        modifier::CalendarYearFullStandardRange::default(),
251    ),
252    FormatDescriptionV3Inner::BorrowedLiteral("-"),
253    FormatDescriptionV3Inner::MonthNumerical(modifier::MonthNumerical::default()),
254    FormatDescriptionV3Inner::BorrowedLiteral("-"),
255    FormatDescriptionV3Inner::Day(modifier::Day::default()),
256])
257.into_opaque();
258
259impl Serialize for Date {
260    #[inline]
261    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
262    where
263        S: Serializer,
264    {
265        #[cfg(feature = "serde-human-readable")]
266        if serializer.is_human_readable() {
267            let Ok(s) = self.format(&DATE_FORMAT) else {
268                return Err(S::Error::custom("failed formatting `Date`"));
269            };
270            return serializer.serialize_str(&s);
271        }
272
273        (self.year(), self.ordinal()).serialize(serializer)
274    }
275}
276
277impl<'a> Deserialize<'a> for Date {
278    #[inline]
279    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
280    where
281        D: Deserializer<'a>,
282    {
283        if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
284            deserializer.deserialize_any(Visitor::<Self>(PhantomData))
285        } else {
286            deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
287        }
288    }
289}
290
291impl Serialize for Duration {
292    #[inline]
293    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
294    where
295        S: Serializer,
296    {
297        #[cfg(feature = "serde-human-readable")]
298        if serializer.is_human_readable() {
299            return serializer.collect_str(&format_args!(
300                "{}{}.{:>09}",
301                if self.is_negative() { "-" } else { "" },
302                self.whole_seconds().unsigned_abs(),
303                self.subsec_nanoseconds().abs(),
304            ));
305        }
306
307        (self.whole_seconds(), self.subsec_nanoseconds()).serialize(serializer)
308    }
309}
310
311impl<'a> Deserialize<'a> for Duration {
312    #[inline]
313    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
314    where
315        D: Deserializer<'a>,
316    {
317        if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
318            deserializer.deserialize_any(Visitor::<Self>(PhantomData))
319        } else {
320            deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
321        }
322    }
323}
324
325/// The format used when serializing and deserializing a human-readable `OffsetDateTime`.
326#[cfg(feature = "parsing")]
327const OFFSET_DATE_TIME_FORMAT: FormatDescriptionV3<'_> =
328    FormatDescriptionV3Inner::BorrowedCompound(&[
329        #[cfg(feature = "large-dates")]
330        FormatDescriptionV3Inner::CalendarYearFullExtendedRange(
331            modifier::CalendarYearFullExtendedRange::default(),
332        ),
333        #[cfg(not(feature = "large-dates"))]
334        FormatDescriptionV3Inner::CalendarYearFullStandardRange(
335            modifier::CalendarYearFullStandardRange::default(),
336        ),
337        FormatDescriptionV3Inner::BorrowedLiteral("-"),
338        FormatDescriptionV3Inner::MonthNumerical(modifier::MonthNumerical::default()),
339        FormatDescriptionV3Inner::BorrowedLiteral("-"),
340        FormatDescriptionV3Inner::Day(modifier::Day::default()),
341        FormatDescriptionV3Inner::BorrowedLiteral(" "),
342        FormatDescriptionV3Inner::Hour24(modifier::Hour24::default()),
343        FormatDescriptionV3Inner::BorrowedLiteral(":"),
344        FormatDescriptionV3Inner::Minute(modifier::Minute::default()),
345        FormatDescriptionV3Inner::BorrowedLiteral(":"),
346        FormatDescriptionV3Inner::Second(modifier::Second::default()),
347        FormatDescriptionV3Inner::BorrowedLiteral("."),
348        FormatDescriptionV3Inner::Subsecond(modifier::Subsecond::default()),
349        FormatDescriptionV3Inner::BorrowedLiteral(" "),
350        FormatDescriptionV3Inner::OffsetHour(
351            modifier::OffsetHour::default().with_sign_is_mandatory(true),
352        ),
353        FormatDescriptionV3Inner::BorrowedLiteral(":"),
354        FormatDescriptionV3Inner::OffsetMinute(modifier::OffsetMinute::default()),
355        FormatDescriptionV3Inner::BorrowedLiteral(":"),
356        FormatDescriptionV3Inner::OffsetSecond(modifier::OffsetSecond::default()),
357    ])
358    .into_opaque();
359
360impl Serialize for OffsetDateTime {
361    #[inline]
362    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
363    where
364        S: Serializer,
365    {
366        #[cfg(feature = "serde-human-readable")]
367        if serializer.is_human_readable() {
368            let Ok(s) = self.format(&OFFSET_DATE_TIME_FORMAT) else {
369                return Err(S::Error::custom("failed formatting `OffsetDateTime`"));
370            };
371            return serializer.serialize_str(&s);
372        }
373
374        (
375            self.year(),
376            self.ordinal(),
377            self.hour(),
378            self.minute(),
379            self.second(),
380            self.nanosecond(),
381            self.offset().whole_hours(),
382            self.offset().minutes_past_hour(),
383            self.offset().seconds_past_minute(),
384        )
385            .serialize(serializer)
386    }
387}
388
389impl<'a> Deserialize<'a> for OffsetDateTime {
390    #[inline]
391    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
392    where
393        D: Deserializer<'a>,
394    {
395        if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
396            deserializer.deserialize_any(Visitor::<Self>(PhantomData))
397        } else {
398            deserializer.deserialize_tuple(9, Visitor::<Self>(PhantomData))
399        }
400    }
401}
402
403/// The format used when serializing and deserializing a human-readable `PrimitiveDateTime`.
404#[cfg(feature = "parsing")]
405const PRIMITIVE_DATE_TIME_FORMAT: FormatDescriptionV3<'_> =
406    FormatDescriptionV3Inner::BorrowedCompound(&[
407        #[cfg(feature = "large-dates")]
408        FormatDescriptionV3Inner::CalendarYearFullExtendedRange(
409            modifier::CalendarYearFullExtendedRange::default(),
410        ),
411        #[cfg(not(feature = "large-dates"))]
412        FormatDescriptionV3Inner::CalendarYearFullStandardRange(
413            modifier::CalendarYearFullStandardRange::default(),
414        ),
415        FormatDescriptionV3Inner::BorrowedLiteral("-"),
416        FormatDescriptionV3Inner::MonthNumerical(modifier::MonthNumerical::default()),
417        FormatDescriptionV3Inner::BorrowedLiteral("-"),
418        FormatDescriptionV3Inner::Day(modifier::Day::default()),
419        FormatDescriptionV3Inner::BorrowedLiteral(" "),
420        FormatDescriptionV3Inner::Hour24(modifier::Hour24::default()),
421        FormatDescriptionV3Inner::BorrowedLiteral(":"),
422        FormatDescriptionV3Inner::Minute(modifier::Minute::default()),
423        FormatDescriptionV3Inner::BorrowedLiteral(":"),
424        FormatDescriptionV3Inner::Second(modifier::Second::default()),
425        FormatDescriptionV3Inner::BorrowedLiteral("."),
426        FormatDescriptionV3Inner::Subsecond(modifier::Subsecond::default()),
427    ])
428    .into_opaque();
429
430impl Serialize for PrimitiveDateTime {
431    #[inline]
432    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
433    where
434        S: Serializer,
435    {
436        #[cfg(feature = "serde-human-readable")]
437        if serializer.is_human_readable() {
438            let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else {
439                return Err(S::Error::custom("failed formatting `PrimitiveDateTime`"));
440            };
441            return serializer.serialize_str(&s);
442        }
443
444        (
445            self.year(),
446            self.ordinal(),
447            self.hour(),
448            self.minute(),
449            self.second(),
450            self.nanosecond(),
451        )
452            .serialize(serializer)
453    }
454}
455
456impl<'a> Deserialize<'a> for PrimitiveDateTime {
457    #[inline]
458    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
459    where
460        D: Deserializer<'a>,
461    {
462        if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
463            deserializer.deserialize_any(Visitor::<Self>(PhantomData))
464        } else {
465            deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
466        }
467    }
468}
469
470/// The format used when serializing and deserializing a human-readable `UtcDateTime`.
471#[cfg(feature = "parsing")]
472const UTC_DATE_TIME_FORMAT: FormatDescriptionV3<'_> = PRIMITIVE_DATE_TIME_FORMAT;
473
474impl Serialize for UtcDateTime {
475    #[inline]
476    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
477    where
478        S: Serializer,
479    {
480        #[cfg(feature = "serde-human-readable")]
481        if serializer.is_human_readable() {
482            let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else {
483                return Err(S::Error::custom("failed formatting `UtcDateTime`"));
484            };
485            return serializer.serialize_str(&s);
486        }
487
488        (
489            self.year(),
490            self.ordinal(),
491            self.hour(),
492            self.minute(),
493            self.second(),
494            self.nanosecond(),
495        )
496            .serialize(serializer)
497    }
498}
499
500impl<'a> Deserialize<'a> for UtcDateTime {
501    #[inline]
502    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
503    where
504        D: Deserializer<'a>,
505    {
506        if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
507            deserializer.deserialize_any(Visitor::<Self>(PhantomData))
508        } else {
509            deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
510        }
511    }
512}
513
514/// The format used when serializing and deserializing a human-readable `Time`.
515#[cfg(feature = "parsing")]
516const TIME_FORMAT: FormatDescriptionV3<'_> = FormatDescriptionV3Inner::BorrowedCompound(&[
517    FormatDescriptionV3Inner::Hour24(modifier::Hour24::default()),
518    FormatDescriptionV3Inner::BorrowedLiteral(":"),
519    FormatDescriptionV3Inner::Minute(modifier::Minute::default()),
520    FormatDescriptionV3Inner::BorrowedLiteral(":"),
521    FormatDescriptionV3Inner::Second(modifier::Second::default()),
522    FormatDescriptionV3Inner::BorrowedLiteral("."),
523    FormatDescriptionV3Inner::Subsecond(modifier::Subsecond::default()),
524])
525.into_opaque();
526
527impl Serialize for Time {
528    #[inline]
529    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
530    where
531        S: Serializer,
532    {
533        #[cfg(feature = "serde-human-readable")]
534        if serializer.is_human_readable() {
535            let Ok(s) = self.format(&TIME_FORMAT) else {
536                return Err(S::Error::custom("failed formatting `Time`"));
537            };
538            return serializer.serialize_str(&s);
539        }
540
541        (self.hour(), self.minute(), self.second(), self.nanosecond()).serialize(serializer)
542    }
543}
544
545impl<'a> Deserialize<'a> for Time {
546    #[inline]
547    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
548    where
549        D: Deserializer<'a>,
550    {
551        if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
552            deserializer.deserialize_any(Visitor::<Self>(PhantomData))
553        } else {
554            deserializer.deserialize_tuple(4, Visitor::<Self>(PhantomData))
555        }
556    }
557}
558
559/// The format used when serializing and deserializing a human-readable `UtcOffset`.
560#[cfg(feature = "parsing")]
561const UTC_OFFSET_FORMAT: FormatDescriptionV3<'_> = FormatDescriptionV3Inner::BorrowedCompound(&[
562    FormatDescriptionV3Inner::OffsetHour(
563        modifier::OffsetHour::default().with_sign_is_mandatory(true),
564    ),
565    FormatDescriptionV3Inner::BorrowedLiteral(":"),
566    FormatDescriptionV3Inner::OffsetMinute(modifier::OffsetMinute::default()),
567    FormatDescriptionV3Inner::BorrowedLiteral(":"),
568    FormatDescriptionV3Inner::OffsetSecond(modifier::OffsetSecond::default()),
569])
570.into_opaque();
571
572impl Serialize for UtcOffset {
573    #[inline]
574    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
575    where
576        S: Serializer,
577    {
578        #[cfg(feature = "serde-human-readable")]
579        if serializer.is_human_readable() {
580            let Ok(s) = self.format(&UTC_OFFSET_FORMAT) else {
581                return Err(S::Error::custom("failed formatting `UtcOffset`"));
582            };
583            return serializer.serialize_str(&s);
584        }
585
586        (
587            self.whole_hours(),
588            self.minutes_past_hour(),
589            self.seconds_past_minute(),
590        )
591            .serialize(serializer)
592    }
593}
594
595impl<'a> Deserialize<'a> for UtcOffset {
596    #[inline]
597    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
598    where
599        D: Deserializer<'a>,
600    {
601        if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
602            deserializer.deserialize_any(Visitor::<Self>(PhantomData))
603        } else {
604            deserializer.deserialize_tuple(3, Visitor::<Self>(PhantomData))
605        }
606    }
607}
608
609impl Serialize for Timestamp {
610    #[inline]
611    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
612    where
613        S: Serializer,
614    {
615        self.as_nanoseconds().serialize(serializer)
616    }
617}
618
619impl<'a> Deserialize<'a> for Timestamp {
620    #[inline]
621    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
622    where
623        D: Deserializer<'a>,
624    {
625        deserializer.deserialize_i128(Visitor::<Self>(PhantomData))
626    }
627}
628
629impl Serialize for Weekday {
630    #[inline]
631    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
632    where
633        S: Serializer,
634    {
635        #[cfg(feature = "serde-human-readable")]
636        if serializer.is_human_readable() {
637            #[cfg(not(feature = "std"))]
638            use alloc::string::ToString;
639            return self.to_string().serialize(serializer);
640        }
641
642        self.number_from_monday().serialize(serializer)
643    }
644}
645
646impl<'a> Deserialize<'a> for Weekday {
647    #[inline]
648    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
649    where
650        D: Deserializer<'a>,
651    {
652        if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
653            deserializer.deserialize_any(Visitor::<Self>(PhantomData))
654        } else {
655            deserializer.deserialize_u8(Visitor::<Self>(PhantomData))
656        }
657    }
658}
659
660impl Serialize for Month {
661    #[inline]
662    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
663    where
664        S: Serializer,
665    {
666        #[cfg(feature = "serde-human-readable")]
667        if serializer.is_human_readable() {
668            #[cfg(not(feature = "std"))]
669            use alloc::string::String;
670            return self.to_string().serialize(serializer);
671        }
672
673        u8::from(*self).serialize(serializer)
674    }
675}
676
677impl<'a> Deserialize<'a> for Month {
678    #[inline]
679    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
680    where
681        D: Deserializer<'a>,
682    {
683        if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
684            deserializer.deserialize_any(Visitor::<Self>(PhantomData))
685        } else {
686            deserializer.deserialize_u8(Visitor::<Self>(PhantomData))
687        }
688    }
689}