chrono/datetime/
serde.rs

1use core::fmt;
2use serde::{de, ser};
3
4use super::DateTime;
5use crate::format::{SecondsFormat, write_rfc3339};
6#[cfg(feature = "clock")]
7use crate::offset::Local;
8use crate::offset::{FixedOffset, Offset, TimeZone, Utc};
9
10#[doc(hidden)]
11#[derive(Debug)]
12pub struct SecondsTimestampVisitor;
13
14#[doc(hidden)]
15#[derive(Debug)]
16pub struct NanoSecondsTimestampVisitor;
17
18#[doc(hidden)]
19#[derive(Debug)]
20pub struct MicroSecondsTimestampVisitor;
21
22#[doc(hidden)]
23#[derive(Debug)]
24pub struct MilliSecondsTimestampVisitor;
25
26/// Serialize to an RFC 3339 formatted string
27///
28/// As an extension to RFC 3339 this can serialize `DateTime`s outside the range of 0-9999 years
29/// using an ISO 8601 syntax (which prepends an `-` or `+`).
30///
31/// See [the `serde` module](crate::serde) for alternate serializations.
32impl<Tz: TimeZone> ser::Serialize for DateTime<Tz> {
33    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
34    where
35        S: ser::Serializer,
36    {
37        struct FormatIso8601<'a, Tz: TimeZone> {
38            inner: &'a DateTime<Tz>,
39        }
40
41        impl<Tz: TimeZone> fmt::Display for FormatIso8601<'_, Tz> {
42            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
43                let naive = self.inner.naive_local();
44                let offset = self.inner.offset.fix();
45                write_rfc3339(f, naive, offset, SecondsFormat::AutoSi, true)
46            }
47        }
48
49        serializer.collect_str(&FormatIso8601 { inner: self })
50    }
51}
52
53struct DateTimeVisitor;
54
55impl de::Visitor<'_> for DateTimeVisitor {
56    type Value = DateTime<FixedOffset>;
57
58    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
59        formatter.write_str("an RFC 3339 formatted date and time string")
60    }
61
62    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
63    where
64        E: de::Error,
65    {
66        value.parse().map_err(E::custom)
67    }
68}
69
70/// Deserialize an RFC 3339 formatted string into a `DateTime<FixedOffset>`
71///
72/// As an extension to RFC 3339 this can deserialize to `DateTime`s outside the range of 0-9999
73/// years using an ISO 8601 syntax (which prepends an `-` or `+`).
74///
75/// See [the `serde` module](crate::serde) for alternate deserialization formats.
76impl<'de> de::Deserialize<'de> for DateTime<FixedOffset> {
77    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
78    where
79        D: de::Deserializer<'de>,
80    {
81        deserializer.deserialize_str(DateTimeVisitor)
82    }
83}
84
85/// Deserialize an RFC 3339 formatted string into a `DateTime<Utc>`
86///
87/// If the value contains an offset from UTC that is not zero, the value will be converted to UTC.
88///
89/// As an extension to RFC 3339 this can deserialize to `DateTime`s outside the range of 0-9999
90/// years using an ISO 8601 syntax (which prepends an `-` or `+`).
91///
92/// See [the `serde` module](crate::serde) for alternate deserialization formats.
93impl<'de> de::Deserialize<'de> for DateTime<Utc> {
94    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
95    where
96        D: de::Deserializer<'de>,
97    {
98        deserializer.deserialize_str(DateTimeVisitor).map(|dt| dt.with_timezone(&Utc))
99    }
100}
101
102/// Deserialize an RFC 3339 formatted string into a `DateTime<Local>`
103///
104/// The value will remain the same instant in UTC, but the offset will be recalculated to match
105/// that of the `Local` platform time zone.
106///
107/// As an extension to RFC 3339 this can deserialize to `DateTime`s outside the range of 0-9999
108/// years using an ISO 8601 syntax (which prepends an `-` or `+`).
109///
110/// See [the `serde` module](crate::serde) for alternate deserialization formats.
111#[cfg(feature = "clock")]
112impl<'de> de::Deserialize<'de> for DateTime<Local> {
113    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
114    where
115        D: de::Deserializer<'de>,
116    {
117        deserializer.deserialize_str(DateTimeVisitor).map(|dt| dt.with_timezone(&Local))
118    }
119}
120
121/// Ser/de to/from timestamps in nanoseconds
122///
123/// Intended for use with `serde`'s `with` attribute.
124///
125/// # Example:
126///
127/// ```rust
128/// # use chrono::{DateTime, Utc, NaiveDate};
129/// # use serde_derive::{Deserialize, Serialize};
130/// use chrono::serde::ts_nanoseconds;
131/// #[derive(Deserialize, Serialize)]
132/// struct S {
133///     #[serde(with = "ts_nanoseconds")]
134///     time: DateTime<Utc>,
135/// }
136///
137/// let time = NaiveDate::from_ymd_opt(2018, 5, 17)
138///     .unwrap()
139///     .and_hms_nano_opt(02, 04, 59, 918355733)
140///     .unwrap()
141///     .and_utc();
142/// let my_s = S { time: time.clone() };
143///
144/// let as_string = serde_json::to_string(&my_s)?;
145/// assert_eq!(as_string, r#"{"time":1526522699918355733}"#);
146/// let my_s: S = serde_json::from_str(&as_string)?;
147/// assert_eq!(my_s.time, time);
148/// # Ok::<(), serde_json::Error>(())
149/// ```
150pub mod ts_nanoseconds {
151    use core::fmt;
152    use serde::{de, ser};
153
154    use crate::serde::invalid_ts;
155    use crate::{DateTime, Utc};
156
157    use super::NanoSecondsTimestampVisitor;
158
159    /// Serialize a UTC datetime into an integer number of nanoseconds since the epoch
160    ///
161    /// Intended for use with `serde`s `serialize_with` attribute.
162    ///
163    /// # Errors
164    ///
165    /// An `i64` with nanosecond precision can span a range of ~584 years. This function returns an
166    /// error on an out of range `DateTime`.
167    ///
168    /// The dates that can be represented as nanoseconds are between 1677-09-21T00:12:44.0 and
169    /// 2262-04-11T23:47:16.854775804.
170    ///
171    /// # Example:
172    ///
173    /// ```rust
174    /// # use chrono::{DateTime, Utc, NaiveDate};
175    /// # use serde_derive::Serialize;
176    /// use chrono::serde::ts_nanoseconds::serialize as to_nano_ts;
177    /// #[derive(Serialize)]
178    /// struct S {
179    ///     #[serde(serialize_with = "to_nano_ts")]
180    ///     time: DateTime<Utc>,
181    /// }
182    ///
183    /// let my_s = S {
184    ///     time: NaiveDate::from_ymd_opt(2018, 5, 17)
185    ///         .unwrap()
186    ///         .and_hms_nano_opt(02, 04, 59, 918355733)
187    ///         .unwrap()
188    ///         .and_utc(),
189    /// };
190    /// let as_string = serde_json::to_string(&my_s)?;
191    /// assert_eq!(as_string, r#"{"time":1526522699918355733}"#);
192    /// # Ok::<(), serde_json::Error>(())
193    /// ```
194    pub fn serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
195    where
196        S: ser::Serializer,
197    {
198        serializer.serialize_i64(dt.timestamp_nanos_opt().ok_or(ser::Error::custom(
199            "value out of range for a timestamp with nanosecond precision",
200        ))?)
201    }
202
203    /// Deserialize a [`DateTime`] from a nanosecond timestamp
204    ///
205    /// Intended for use with `serde`s `deserialize_with` attribute.
206    ///
207    /// # Example:
208    ///
209    /// ```rust
210    /// # use chrono::{DateTime, TimeZone, Utc};
211    /// # use serde_derive::Deserialize;
212    /// use chrono::serde::ts_nanoseconds::deserialize as from_nano_ts;
213    /// #[derive(Debug, PartialEq, Deserialize)]
214    /// struct S {
215    ///     #[serde(deserialize_with = "from_nano_ts")]
216    ///     time: DateTime<Utc>,
217    /// }
218    ///
219    /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355733 }"#)?;
220    /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1526522699, 918355733).unwrap() });
221    ///
222    /// let my_s: S = serde_json::from_str(r#"{ "time": -1 }"#)?;
223    /// assert_eq!(my_s, S { time: Utc.timestamp_opt(-1, 999_999_999).unwrap() });
224    /// # Ok::<(), serde_json::Error>(())
225    /// ```
226    pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
227    where
228        D: de::Deserializer<'de>,
229    {
230        d.deserialize_i64(NanoSecondsTimestampVisitor)
231    }
232
233    impl de::Visitor<'_> for NanoSecondsTimestampVisitor {
234        type Value = DateTime<Utc>;
235
236        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
237            formatter.write_str("a unix timestamp in nanoseconds")
238        }
239
240        /// Deserialize a timestamp in nanoseconds since the epoch
241        fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
242        where
243            E: de::Error,
244        {
245            Ok(DateTime::from_timestamp_nanos(value))
246        }
247
248        /// Deserialize a timestamp in nanoseconds since the epoch
249        fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
250        where
251            E: de::Error,
252        {
253            DateTime::from_timestamp((value / 1_000_000_000) as i64, (value % 1_000_000_000) as u32)
254                .ok_or_else(|| invalid_ts(value))
255        }
256    }
257}
258
259/// Ser/de to/from optional timestamps in nanoseconds
260///
261/// Intended for use with `serde`'s `with` attribute.
262///
263/// # Example:
264///
265/// ```rust
266/// # use chrono::{DateTime, Utc, NaiveDate};
267/// # use serde_derive::{Deserialize, Serialize};
268/// use chrono::serde::ts_nanoseconds_option;
269/// #[derive(Deserialize, Serialize)]
270/// struct S {
271///     #[serde(with = "ts_nanoseconds_option")]
272///     time: Option<DateTime<Utc>>,
273/// }
274///
275/// let time = Some(
276///     NaiveDate::from_ymd_opt(2018, 5, 17)
277///         .unwrap()
278///         .and_hms_nano_opt(02, 04, 59, 918355733)
279///         .unwrap()
280///         .and_utc(),
281/// );
282/// let my_s = S { time: time.clone() };
283///
284/// let as_string = serde_json::to_string(&my_s)?;
285/// assert_eq!(as_string, r#"{"time":1526522699918355733}"#);
286/// let my_s: S = serde_json::from_str(&as_string)?;
287/// assert_eq!(my_s.time, time);
288/// # Ok::<(), serde_json::Error>(())
289/// ```
290pub mod ts_nanoseconds_option {
291    use core::fmt;
292    use serde::{de, ser};
293
294    use crate::{DateTime, Utc};
295
296    use super::NanoSecondsTimestampVisitor;
297
298    /// Serialize a UTC datetime into an integer number of nanoseconds since the epoch or none
299    ///
300    /// Intended for use with `serde`s `serialize_with` attribute.
301    ///
302    /// # Errors
303    ///
304    /// An `i64` with nanosecond precision can span a range of ~584 years. This function returns an
305    /// error on an out of range `DateTime`.
306    ///
307    /// The dates that can be represented as nanoseconds are between 1677-09-21T00:12:44.0 and
308    /// 2262-04-11T23:47:16.854775804.
309    ///
310    /// # Example:
311    ///
312    /// ```rust
313    /// # use chrono::{DateTime, Utc, NaiveDate};
314    /// # use serde_derive::Serialize;
315    /// use chrono::serde::ts_nanoseconds_option::serialize as to_nano_tsopt;
316    /// #[derive(Serialize)]
317    /// struct S {
318    ///     #[serde(serialize_with = "to_nano_tsopt")]
319    ///     time: Option<DateTime<Utc>>,
320    /// }
321    ///
322    /// let my_s = S {
323    ///     time: Some(
324    ///         NaiveDate::from_ymd_opt(2018, 5, 17)
325    ///             .unwrap()
326    ///             .and_hms_nano_opt(02, 04, 59, 918355733)
327    ///             .unwrap()
328    ///             .and_utc(),
329    ///     ),
330    /// };
331    /// let as_string = serde_json::to_string(&my_s)?;
332    /// assert_eq!(as_string, r#"{"time":1526522699918355733}"#);
333    /// # Ok::<(), serde_json::Error>(())
334    /// ```
335    pub fn serialize<S>(opt: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
336    where
337        S: ser::Serializer,
338    {
339        match *opt {
340            Some(ref dt) => serializer.serialize_some(&dt.timestamp_nanos_opt().ok_or(
341                ser::Error::custom("value out of range for a timestamp with nanosecond precision"),
342            )?),
343            None => serializer.serialize_none(),
344        }
345    }
346
347    /// Deserialize a `DateTime` from a nanosecond timestamp or none
348    ///
349    /// Intended for use with `serde`s `deserialize_with` attribute.
350    ///
351    /// # Example:
352    ///
353    /// ```rust
354    /// # use chrono::{DateTime, TimeZone, Utc};
355    /// # use serde_derive::Deserialize;
356    /// use chrono::serde::ts_nanoseconds_option::deserialize as from_nano_tsopt;
357    /// #[derive(Debug, PartialEq, Deserialize)]
358    /// struct S {
359    ///     #[serde(deserialize_with = "from_nano_tsopt")]
360    ///     time: Option<DateTime<Utc>>,
361    /// }
362    ///
363    /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355733 }"#)?;
364    /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1526522699, 918355733).single() });
365    /// # Ok::<(), serde_json::Error>(())
366    /// ```
367    pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error>
368    where
369        D: de::Deserializer<'de>,
370    {
371        d.deserialize_option(OptionNanoSecondsTimestampVisitor)
372    }
373
374    struct OptionNanoSecondsTimestampVisitor;
375
376    impl<'de> de::Visitor<'de> for OptionNanoSecondsTimestampVisitor {
377        type Value = Option<DateTime<Utc>>;
378
379        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
380            formatter.write_str("a unix timestamp in nanoseconds or none")
381        }
382
383        /// Deserialize a timestamp in nanoseconds since the epoch
384        fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error>
385        where
386            D: de::Deserializer<'de>,
387        {
388            d.deserialize_i64(NanoSecondsTimestampVisitor).map(Some)
389        }
390
391        /// Deserialize a timestamp in nanoseconds since the epoch
392        fn visit_none<E>(self) -> Result<Self::Value, E>
393        where
394            E: de::Error,
395        {
396            Ok(None)
397        }
398
399        /// Deserialize a timestamp in nanoseconds since the epoch
400        fn visit_unit<E>(self) -> Result<Self::Value, E>
401        where
402            E: de::Error,
403        {
404            Ok(None)
405        }
406    }
407}
408
409/// Ser/de to/from timestamps in microseconds
410///
411/// Intended for use with `serde`'s `with` attribute.
412///
413/// # Example:
414///
415/// ```rust
416/// # use chrono::{DateTime, Utc, NaiveDate};
417/// # use serde_derive::{Deserialize, Serialize};
418/// use chrono::serde::ts_microseconds;
419/// #[derive(Deserialize, Serialize)]
420/// struct S {
421///     #[serde(with = "ts_microseconds")]
422///     time: DateTime<Utc>,
423/// }
424///
425/// let time = NaiveDate::from_ymd_opt(2018, 5, 17)
426///     .unwrap()
427///     .and_hms_micro_opt(02, 04, 59, 918355)
428///     .unwrap()
429///     .and_utc();
430/// let my_s = S { time: time.clone() };
431///
432/// let as_string = serde_json::to_string(&my_s)?;
433/// assert_eq!(as_string, r#"{"time":1526522699918355}"#);
434/// let my_s: S = serde_json::from_str(&as_string)?;
435/// assert_eq!(my_s.time, time);
436/// # Ok::<(), serde_json::Error>(())
437/// ```
438pub mod ts_microseconds {
439    use core::fmt;
440    use serde::{de, ser};
441
442    use crate::serde::invalid_ts;
443    use crate::{DateTime, Utc};
444
445    use super::MicroSecondsTimestampVisitor;
446
447    /// Serialize a UTC datetime into an integer number of microseconds since the epoch
448    ///
449    /// Intended for use with `serde`s `serialize_with` attribute.
450    ///
451    /// # Example:
452    ///
453    /// ```rust
454    /// # use chrono::{DateTime, Utc, NaiveDate};
455    /// # use serde_derive::Serialize;
456    /// use chrono::serde::ts_microseconds::serialize as to_micro_ts;
457    /// #[derive(Serialize)]
458    /// struct S {
459    ///     #[serde(serialize_with = "to_micro_ts")]
460    ///     time: DateTime<Utc>,
461    /// }
462    ///
463    /// let my_s = S {
464    ///     time: NaiveDate::from_ymd_opt(2018, 5, 17)
465    ///         .unwrap()
466    ///         .and_hms_micro_opt(02, 04, 59, 918355)
467    ///         .unwrap()
468    ///         .and_utc(),
469    /// };
470    /// let as_string = serde_json::to_string(&my_s)?;
471    /// assert_eq!(as_string, r#"{"time":1526522699918355}"#);
472    /// # Ok::<(), serde_json::Error>(())
473    /// ```
474    pub fn serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
475    where
476        S: ser::Serializer,
477    {
478        serializer.serialize_i64(dt.timestamp_micros())
479    }
480
481    /// Deserialize a `DateTime` from a microsecond timestamp
482    ///
483    /// Intended for use with `serde`s `deserialize_with` attribute.
484    ///
485    /// # Example:
486    ///
487    /// ```rust
488    /// # use chrono::{DateTime, TimeZone, Utc};
489    /// # use serde_derive::Deserialize;
490    /// use chrono::serde::ts_microseconds::deserialize as from_micro_ts;
491    /// #[derive(Debug, PartialEq, Deserialize)]
492    /// struct S {
493    ///     #[serde(deserialize_with = "from_micro_ts")]
494    ///     time: DateTime<Utc>,
495    /// }
496    ///
497    /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355 }"#)?;
498    /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1526522699, 918355000).unwrap() });
499    ///
500    /// let my_s: S = serde_json::from_str(r#"{ "time": -1 }"#)?;
501    /// assert_eq!(my_s, S { time: Utc.timestamp_opt(-1, 999_999_000).unwrap() });
502    /// # Ok::<(), serde_json::Error>(())
503    /// ```
504    pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
505    where
506        D: de::Deserializer<'de>,
507    {
508        d.deserialize_i64(MicroSecondsTimestampVisitor)
509    }
510
511    impl de::Visitor<'_> for MicroSecondsTimestampVisitor {
512        type Value = DateTime<Utc>;
513
514        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
515            formatter.write_str("a unix timestamp in microseconds")
516        }
517
518        /// Deserialize a timestamp in milliseconds since the epoch
519        fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
520        where
521            E: de::Error,
522        {
523            DateTime::from_timestamp_micros(value).ok_or_else(|| invalid_ts(value))
524        }
525
526        /// Deserialize a timestamp in milliseconds since the epoch
527        fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
528        where
529            E: de::Error,
530        {
531            DateTime::from_timestamp(
532                (value / 1_000_000) as i64,
533                ((value % 1_000_000) * 1_000) as u32,
534            )
535            .ok_or_else(|| invalid_ts(value))
536        }
537    }
538}
539
540/// Ser/de to/from optional timestamps in microseconds
541///
542/// Intended for use with `serde`'s `with` attribute.
543///
544/// # Example:
545///
546/// ```rust
547/// # use chrono::{DateTime, Utc, NaiveDate};
548/// # use serde_derive::{Deserialize, Serialize};
549/// use chrono::serde::ts_microseconds_option;
550/// #[derive(Deserialize, Serialize)]
551/// struct S {
552///     #[serde(with = "ts_microseconds_option")]
553///     time: Option<DateTime<Utc>>,
554/// }
555///
556/// let time = Some(
557///     NaiveDate::from_ymd_opt(2018, 5, 17)
558///         .unwrap()
559///         .and_hms_micro_opt(02, 04, 59, 918355)
560///         .unwrap()
561///         .and_utc(),
562/// );
563/// let my_s = S { time: time.clone() };
564///
565/// let as_string = serde_json::to_string(&my_s)?;
566/// assert_eq!(as_string, r#"{"time":1526522699918355}"#);
567/// let my_s: S = serde_json::from_str(&as_string)?;
568/// assert_eq!(my_s.time, time);
569/// # Ok::<(), serde_json::Error>(())
570/// ```
571pub mod ts_microseconds_option {
572    use core::fmt;
573    use serde::{de, ser};
574
575    use super::MicroSecondsTimestampVisitor;
576    use crate::{DateTime, Utc};
577
578    /// Serialize a UTC datetime into an integer number of microseconds since the epoch or none
579    ///
580    /// Intended for use with `serde`s `serialize_with` attribute.
581    ///
582    /// # Example:
583    ///
584    /// ```rust
585    /// # use chrono::{DateTime, Utc, NaiveDate};
586    /// # use serde_derive::Serialize;
587    /// use chrono::serde::ts_microseconds_option::serialize as to_micro_tsopt;
588    /// #[derive(Serialize)]
589    /// struct S {
590    ///     #[serde(serialize_with = "to_micro_tsopt")]
591    ///     time: Option<DateTime<Utc>>,
592    /// }
593    ///
594    /// let my_s = S {
595    ///     time: Some(
596    ///         NaiveDate::from_ymd_opt(2018, 5, 17)
597    ///             .unwrap()
598    ///             .and_hms_micro_opt(02, 04, 59, 918355)
599    ///             .unwrap()
600    ///             .and_utc(),
601    ///     ),
602    /// };
603    /// let as_string = serde_json::to_string(&my_s)?;
604    /// assert_eq!(as_string, r#"{"time":1526522699918355}"#);
605    /// # Ok::<(), serde_json::Error>(())
606    /// ```
607    pub fn serialize<S>(opt: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
608    where
609        S: ser::Serializer,
610    {
611        match *opt {
612            Some(ref dt) => serializer.serialize_some(&dt.timestamp_micros()),
613            None => serializer.serialize_none(),
614        }
615    }
616
617    /// Deserialize a `DateTime` from a microsecond timestamp or none
618    ///
619    /// Intended for use with `serde`s `deserialize_with` attribute.
620    ///
621    /// # Example:
622    ///
623    /// ```rust
624    /// # use chrono::{DateTime, TimeZone, Utc};
625    /// # use serde_derive::Deserialize;
626    /// use chrono::serde::ts_microseconds_option::deserialize as from_micro_tsopt;
627    /// #[derive(Debug, PartialEq, Deserialize)]
628    /// struct S {
629    ///     #[serde(deserialize_with = "from_micro_tsopt")]
630    ///     time: Option<DateTime<Utc>>,
631    /// }
632    ///
633    /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355 }"#)?;
634    /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1526522699, 918355000).single() });
635    /// # Ok::<(), serde_json::Error>(())
636    /// ```
637    pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error>
638    where
639        D: de::Deserializer<'de>,
640    {
641        d.deserialize_option(OptionMicroSecondsTimestampVisitor)
642    }
643
644    struct OptionMicroSecondsTimestampVisitor;
645
646    impl<'de> de::Visitor<'de> for OptionMicroSecondsTimestampVisitor {
647        type Value = Option<DateTime<Utc>>;
648
649        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
650            formatter.write_str("a unix timestamp in microseconds or none")
651        }
652
653        /// Deserialize a timestamp in microseconds since the epoch
654        fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error>
655        where
656            D: de::Deserializer<'de>,
657        {
658            d.deserialize_i64(MicroSecondsTimestampVisitor).map(Some)
659        }
660
661        /// Deserialize a timestamp in microseconds since the epoch
662        fn visit_none<E>(self) -> Result<Self::Value, E>
663        where
664            E: de::Error,
665        {
666            Ok(None)
667        }
668
669        /// Deserialize a timestamp in microseconds since the epoch
670        fn visit_unit<E>(self) -> Result<Self::Value, E>
671        where
672            E: de::Error,
673        {
674            Ok(None)
675        }
676    }
677}
678
679/// Ser/de to/from timestamps in milliseconds
680///
681/// Intended for use with `serde`s `with` attribute.
682///
683/// # Example
684///
685/// ```rust
686/// # use chrono::{DateTime, Utc, NaiveDate};
687/// # use serde_derive::{Deserialize, Serialize};
688/// use chrono::serde::ts_milliseconds;
689/// #[derive(Deserialize, Serialize)]
690/// struct S {
691///     #[serde(with = "ts_milliseconds")]
692///     time: DateTime<Utc>,
693/// }
694///
695/// let time = NaiveDate::from_ymd_opt(2018, 5, 17)
696///     .unwrap()
697///     .and_hms_milli_opt(02, 04, 59, 918)
698///     .unwrap()
699///     .and_utc();
700/// let my_s = S { time: time.clone() };
701///
702/// let as_string = serde_json::to_string(&my_s)?;
703/// assert_eq!(as_string, r#"{"time":1526522699918}"#);
704/// let my_s: S = serde_json::from_str(&as_string)?;
705/// assert_eq!(my_s.time, time);
706/// # Ok::<(), serde_json::Error>(())
707/// ```
708pub mod ts_milliseconds {
709    use core::fmt;
710    use serde::{de, ser};
711
712    use crate::serde::invalid_ts;
713    use crate::{DateTime, Utc};
714
715    use super::MilliSecondsTimestampVisitor;
716
717    /// Serialize a UTC datetime into an integer number of milliseconds since the epoch
718    ///
719    /// Intended for use with `serde`s `serialize_with` attribute.
720    ///
721    /// # Example:
722    ///
723    /// ```rust
724    /// # use chrono::{DateTime, Utc, NaiveDate};
725    /// # use serde_derive::Serialize;
726    /// use chrono::serde::ts_milliseconds::serialize as to_milli_ts;
727    /// #[derive(Serialize)]
728    /// struct S {
729    ///     #[serde(serialize_with = "to_milli_ts")]
730    ///     time: DateTime<Utc>,
731    /// }
732    ///
733    /// let my_s = S {
734    ///     time: NaiveDate::from_ymd_opt(2018, 5, 17)
735    ///         .unwrap()
736    ///         .and_hms_milli_opt(02, 04, 59, 918)
737    ///         .unwrap()
738    ///         .and_utc(),
739    /// };
740    /// let as_string = serde_json::to_string(&my_s)?;
741    /// assert_eq!(as_string, r#"{"time":1526522699918}"#);
742    /// # Ok::<(), serde_json::Error>(())
743    /// ```
744    pub fn serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
745    where
746        S: ser::Serializer,
747    {
748        serializer.serialize_i64(dt.timestamp_millis())
749    }
750
751    /// Deserialize a `DateTime` from a millisecond timestamp
752    ///
753    /// Intended for use with `serde`s `deserialize_with` attribute.
754    ///
755    /// # Example:
756    ///
757    /// ```rust
758    /// # use chrono::{DateTime, TimeZone, Utc};
759    /// # use serde_derive::Deserialize;
760    /// use chrono::serde::ts_milliseconds::deserialize as from_milli_ts;
761    /// #[derive(Debug, PartialEq, Deserialize)]
762    /// struct S {
763    ///     #[serde(deserialize_with = "from_milli_ts")]
764    ///     time: DateTime<Utc>,
765    /// }
766    ///
767    /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918 }"#)?;
768    /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1526522699, 918000000).unwrap() });
769    ///
770    /// let my_s: S = serde_json::from_str(r#"{ "time": -1 }"#)?;
771    /// assert_eq!(my_s, S { time: Utc.timestamp_opt(-1, 999_000_000).unwrap() });
772    /// # Ok::<(), serde_json::Error>(())
773    /// ```
774    pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
775    where
776        D: de::Deserializer<'de>,
777    {
778        d.deserialize_i64(MilliSecondsTimestampVisitor).map(|dt| dt.with_timezone(&Utc))
779    }
780
781    impl de::Visitor<'_> for MilliSecondsTimestampVisitor {
782        type Value = DateTime<Utc>;
783
784        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
785            formatter.write_str("a unix timestamp in milliseconds")
786        }
787
788        /// Deserialize a timestamp in milliseconds since the epoch
789        fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
790        where
791            E: de::Error,
792        {
793            DateTime::from_timestamp_millis(value).ok_or_else(|| invalid_ts(value))
794        }
795
796        /// Deserialize a timestamp in milliseconds since the epoch
797        fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
798        where
799            E: de::Error,
800        {
801            DateTime::from_timestamp((value / 1000) as i64, ((value % 1000) * 1_000_000) as u32)
802                .ok_or_else(|| invalid_ts(value))
803        }
804    }
805}
806
807/// Ser/de to/from optional timestamps in milliseconds
808///
809/// Intended for use with `serde`s `with` attribute.
810///
811/// # Example
812///
813/// ```rust
814/// # use chrono::{DateTime, Utc, NaiveDate};
815/// # use serde_derive::{Deserialize, Serialize};
816/// use chrono::serde::ts_milliseconds_option;
817/// #[derive(Deserialize, Serialize)]
818/// struct S {
819///     #[serde(with = "ts_milliseconds_option")]
820///     time: Option<DateTime<Utc>>,
821/// }
822///
823/// let time = Some(
824///     NaiveDate::from_ymd_opt(2018, 5, 17)
825///         .unwrap()
826///         .and_hms_milli_opt(02, 04, 59, 918)
827///         .unwrap()
828///         .and_utc(),
829/// );
830/// let my_s = S { time: time.clone() };
831///
832/// let as_string = serde_json::to_string(&my_s)?;
833/// assert_eq!(as_string, r#"{"time":1526522699918}"#);
834/// let my_s: S = serde_json::from_str(&as_string)?;
835/// assert_eq!(my_s.time, time);
836/// # Ok::<(), serde_json::Error>(())
837/// ```
838pub mod ts_milliseconds_option {
839    use core::fmt;
840    use serde::{de, ser};
841
842    use super::MilliSecondsTimestampVisitor;
843    use crate::{DateTime, Utc};
844
845    /// Serialize a UTC datetime into an integer number of milliseconds since the epoch or none
846    ///
847    /// Intended for use with `serde`s `serialize_with` attribute.
848    ///
849    /// # Example:
850    ///
851    /// ```rust
852    /// # use chrono::{DateTime, Utc, NaiveDate};
853    /// # use serde_derive::Serialize;
854    /// use chrono::serde::ts_milliseconds_option::serialize as to_milli_tsopt;
855    /// #[derive(Serialize)]
856    /// struct S {
857    ///     #[serde(serialize_with = "to_milli_tsopt")]
858    ///     time: Option<DateTime<Utc>>,
859    /// }
860    ///
861    /// let my_s = S {
862    ///     time: Some(
863    ///         NaiveDate::from_ymd_opt(2018, 5, 17)
864    ///             .unwrap()
865    ///             .and_hms_milli_opt(02, 04, 59, 918)
866    ///             .unwrap()
867    ///             .and_utc(),
868    ///     ),
869    /// };
870    /// let as_string = serde_json::to_string(&my_s)?;
871    /// assert_eq!(as_string, r#"{"time":1526522699918}"#);
872    /// # Ok::<(), serde_json::Error>(())
873    /// ```
874    pub fn serialize<S>(opt: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
875    where
876        S: ser::Serializer,
877    {
878        match *opt {
879            Some(ref dt) => serializer.serialize_some(&dt.timestamp_millis()),
880            None => serializer.serialize_none(),
881        }
882    }
883
884    /// Deserialize a `DateTime` from a millisecond timestamp or none
885    ///
886    /// Intended for use with `serde`s `deserialize_with` attribute.
887    ///
888    /// # Example:
889    ///
890    /// ```rust
891    /// # use chrono::{TimeZone, DateTime, Utc};
892    /// # use serde_derive::Deserialize;
893    /// use chrono::serde::ts_milliseconds_option::deserialize as from_milli_tsopt;
894    ///
895    /// #[derive(Deserialize, PartialEq, Debug)]
896    /// #[serde(untagged)]
897    /// enum E<T> {
898    ///     V(T),
899    /// }
900    ///
901    /// #[derive(Deserialize, PartialEq, Debug)]
902    /// struct S {
903    ///     #[serde(default, deserialize_with = "from_milli_tsopt")]
904    ///     time: Option<DateTime<Utc>>,
905    /// }
906    ///
907    /// let my_s: E<S> = serde_json::from_str(r#"{ "time": 1526522699918 }"#)?;
908    /// assert_eq!(my_s, E::V(S { time: Some(Utc.timestamp_opt(1526522699, 918000000).unwrap()) }));
909    /// let s: E<S> = serde_json::from_str(r#"{ "time": null }"#)?;
910    /// assert_eq!(s, E::V(S { time: None }));
911    /// let t: E<S> = serde_json::from_str(r#"{}"#)?;
912    /// assert_eq!(t, E::V(S { time: None }));
913    /// # Ok::<(), serde_json::Error>(())
914    /// ```
915    pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error>
916    where
917        D: de::Deserializer<'de>,
918    {
919        d.deserialize_option(OptionMilliSecondsTimestampVisitor)
920            .map(|opt| opt.map(|dt| dt.with_timezone(&Utc)))
921    }
922
923    struct OptionMilliSecondsTimestampVisitor;
924
925    impl<'de> de::Visitor<'de> for OptionMilliSecondsTimestampVisitor {
926        type Value = Option<DateTime<Utc>>;
927
928        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
929            formatter.write_str("a unix timestamp in milliseconds or none")
930        }
931
932        /// Deserialize a timestamp in milliseconds since the epoch
933        fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error>
934        where
935            D: de::Deserializer<'de>,
936        {
937            d.deserialize_i64(MilliSecondsTimestampVisitor).map(Some)
938        }
939
940        /// Deserialize a timestamp in milliseconds since the epoch
941        fn visit_none<E>(self) -> Result<Self::Value, E>
942        where
943            E: de::Error,
944        {
945            Ok(None)
946        }
947
948        /// Deserialize a timestamp in milliseconds since the epoch
949        fn visit_unit<E>(self) -> Result<Self::Value, E>
950        where
951            E: de::Error,
952        {
953            Ok(None)
954        }
955    }
956}
957
958/// Ser/de to/from timestamps in seconds
959///
960/// Intended for use with `serde`'s `with` attribute.
961///
962/// # Example:
963///
964/// ```rust
965/// # use chrono::{TimeZone, DateTime, Utc};
966/// # use serde_derive::{Deserialize, Serialize};
967/// use chrono::serde::ts_seconds;
968/// #[derive(Deserialize, Serialize)]
969/// struct S {
970///     #[serde(with = "ts_seconds")]
971///     time: DateTime<Utc>,
972/// }
973///
974/// let time = Utc.with_ymd_and_hms(2015, 5, 15, 10, 0, 0).unwrap();
975/// let my_s = S { time: time.clone() };
976///
977/// let as_string = serde_json::to_string(&my_s)?;
978/// assert_eq!(as_string, r#"{"time":1431684000}"#);
979/// let my_s: S = serde_json::from_str(&as_string)?;
980/// assert_eq!(my_s.time, time);
981/// # Ok::<(), serde_json::Error>(())
982/// ```
983pub mod ts_seconds {
984    use core::fmt;
985    use serde::{de, ser};
986
987    use crate::serde::invalid_ts;
988    use crate::{DateTime, Utc};
989
990    use super::SecondsTimestampVisitor;
991
992    /// Serialize a UTC datetime into an integer number of seconds since the epoch
993    ///
994    /// Intended for use with `serde`s `serialize_with` attribute.
995    ///
996    /// # Example:
997    ///
998    /// ```rust
999    /// # use chrono::{TimeZone, DateTime, Utc};
1000    /// # use serde_derive::Serialize;
1001    /// use chrono::serde::ts_seconds::serialize as to_ts;
1002    /// #[derive(Serialize)]
1003    /// struct S {
1004    ///     #[serde(serialize_with = "to_ts")]
1005    ///     time: DateTime<Utc>,
1006    /// }
1007    ///
1008    /// let my_s = S { time: Utc.with_ymd_and_hms(2015, 5, 15, 10, 0, 0).unwrap() };
1009    /// let as_string = serde_json::to_string(&my_s)?;
1010    /// assert_eq!(as_string, r#"{"time":1431684000}"#);
1011    /// # Ok::<(), serde_json::Error>(())
1012    /// ```
1013    pub fn serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
1014    where
1015        S: ser::Serializer,
1016    {
1017        serializer.serialize_i64(dt.timestamp())
1018    }
1019
1020    /// Deserialize a `DateTime` from a seconds timestamp
1021    ///
1022    /// Intended for use with `serde`s `deserialize_with` attribute.
1023    ///
1024    /// # Example:
1025    ///
1026    /// ```rust
1027    /// # use chrono::{DateTime, TimeZone, Utc};
1028    /// # use serde_derive::Deserialize;
1029    /// use chrono::serde::ts_seconds::deserialize as from_ts;
1030    /// #[derive(Debug, PartialEq, Deserialize)]
1031    /// struct S {
1032    ///     #[serde(deserialize_with = "from_ts")]
1033    ///     time: DateTime<Utc>,
1034    /// }
1035    ///
1036    /// let my_s: S = serde_json::from_str(r#"{ "time": 1431684000 }"#)?;
1037    /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1431684000, 0).unwrap() });
1038    /// # Ok::<(), serde_json::Error>(())
1039    /// ```
1040    pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
1041    where
1042        D: de::Deserializer<'de>,
1043    {
1044        d.deserialize_i64(SecondsTimestampVisitor)
1045    }
1046
1047    impl de::Visitor<'_> for SecondsTimestampVisitor {
1048        type Value = DateTime<Utc>;
1049
1050        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1051            formatter.write_str("a unix timestamp in seconds")
1052        }
1053
1054        /// Deserialize a timestamp in seconds since the epoch
1055        fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
1056        where
1057            E: de::Error,
1058        {
1059            DateTime::from_timestamp_secs(value).ok_or_else(|| invalid_ts(value))
1060        }
1061
1062        /// Deserialize a timestamp in seconds since the epoch
1063        fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
1064        where
1065            E: de::Error,
1066        {
1067            if value > i64::MAX as u64 {
1068                Err(invalid_ts(value))
1069            } else {
1070                DateTime::from_timestamp_secs(value as i64).ok_or_else(|| invalid_ts(value))
1071            }
1072        }
1073    }
1074}
1075
1076/// Ser/de to/from optional timestamps in seconds
1077///
1078/// Intended for use with `serde`'s `with` attribute.
1079///
1080/// # Example:
1081///
1082/// ```rust
1083/// # use chrono::{TimeZone, DateTime, Utc};
1084/// # use serde_derive::{Deserialize, Serialize};
1085/// use chrono::serde::ts_seconds_option;
1086/// #[derive(Deserialize, Serialize)]
1087/// struct S {
1088///     #[serde(with = "ts_seconds_option")]
1089///     time: Option<DateTime<Utc>>,
1090/// }
1091///
1092/// let time = Some(Utc.with_ymd_and_hms(2015, 5, 15, 10, 0, 0).unwrap());
1093/// let my_s = S { time: time.clone() };
1094///
1095/// let as_string = serde_json::to_string(&my_s)?;
1096/// assert_eq!(as_string, r#"{"time":1431684000}"#);
1097/// let my_s: S = serde_json::from_str(&as_string)?;
1098/// assert_eq!(my_s.time, time);
1099/// # Ok::<(), serde_json::Error>(())
1100/// ```
1101pub mod ts_seconds_option {
1102    use core::fmt;
1103    use serde::{de, ser};
1104
1105    use super::SecondsTimestampVisitor;
1106    use crate::{DateTime, Utc};
1107
1108    /// Serialize a UTC datetime into an integer number of seconds since the epoch or none
1109    ///
1110    /// Intended for use with `serde`s `serialize_with` attribute.
1111    ///
1112    /// # Example:
1113    ///
1114    /// ```rust
1115    /// # use chrono::{TimeZone, DateTime, Utc};
1116    /// # use serde_derive::Serialize;
1117    /// use chrono::serde::ts_seconds_option::serialize as to_tsopt;
1118    /// #[derive(Serialize)]
1119    /// struct S {
1120    ///     #[serde(serialize_with = "to_tsopt")]
1121    ///     time: Option<DateTime<Utc>>,
1122    /// }
1123    ///
1124    /// let my_s = S { time: Some(Utc.with_ymd_and_hms(2015, 5, 15, 10, 0, 0).unwrap()) };
1125    /// let as_string = serde_json::to_string(&my_s)?;
1126    /// assert_eq!(as_string, r#"{"time":1431684000}"#);
1127    /// # Ok::<(), serde_json::Error>(())
1128    /// ```
1129    pub fn serialize<S>(opt: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
1130    where
1131        S: ser::Serializer,
1132    {
1133        match *opt {
1134            Some(ref dt) => serializer.serialize_some(&dt.timestamp()),
1135            None => serializer.serialize_none(),
1136        }
1137    }
1138
1139    /// Deserialize a `DateTime` from a seconds timestamp or none
1140    ///
1141    /// Intended for use with `serde`s `deserialize_with` attribute.
1142    ///
1143    /// # Example:
1144    ///
1145    /// ```rust
1146    /// # use chrono::{DateTime, TimeZone, Utc};
1147    /// # use serde_derive::Deserialize;
1148    /// use chrono::serde::ts_seconds_option::deserialize as from_tsopt;
1149    /// #[derive(Debug, PartialEq, Deserialize)]
1150    /// struct S {
1151    ///     #[serde(deserialize_with = "from_tsopt")]
1152    ///     time: Option<DateTime<Utc>>,
1153    /// }
1154    ///
1155    /// let my_s: S = serde_json::from_str(r#"{ "time": 1431684000 }"#)?;
1156    /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1431684000, 0).single() });
1157    /// # Ok::<(), serde_json::Error>(())
1158    /// ```
1159    pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error>
1160    where
1161        D: de::Deserializer<'de>,
1162    {
1163        d.deserialize_option(OptionSecondsTimestampVisitor)
1164    }
1165
1166    struct OptionSecondsTimestampVisitor;
1167
1168    impl<'de> de::Visitor<'de> for OptionSecondsTimestampVisitor {
1169        type Value = Option<DateTime<Utc>>;
1170
1171        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1172            formatter.write_str("a unix timestamp in seconds or none")
1173        }
1174
1175        /// Deserialize a timestamp in seconds since the epoch
1176        fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error>
1177        where
1178            D: de::Deserializer<'de>,
1179        {
1180            d.deserialize_i64(SecondsTimestampVisitor).map(Some)
1181        }
1182
1183        /// Deserialize a timestamp in seconds since the epoch
1184        fn visit_none<E>(self) -> Result<Self::Value, E>
1185        where
1186            E: de::Error,
1187        {
1188            Ok(None)
1189        }
1190
1191        /// Deserialize a timestamp in seconds since the epoch
1192        fn visit_unit<E>(self) -> Result<Self::Value, E>
1193        where
1194            E: de::Error,
1195        {
1196            Ok(None)
1197        }
1198    }
1199}
1200
1201#[cfg(test)]
1202mod tests {
1203    #[cfg(feature = "clock")]
1204    use crate::Local;
1205    use crate::{DateTime, FixedOffset, TimeZone, Utc};
1206    use core::fmt;
1207
1208    #[test]
1209    fn test_serde_serialize() {
1210        assert_eq!(
1211            serde_json::to_string(&Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()).ok(),
1212            Some(r#""2014-07-24T12:34:06Z""#.to_owned())
1213        );
1214        assert_eq!(
1215            serde_json::to_string(
1216                &FixedOffset::east_opt(3660)
1217                    .unwrap()
1218                    .with_ymd_and_hms(2014, 7, 24, 12, 34, 6)
1219                    .unwrap()
1220            )
1221            .ok(),
1222            Some(r#""2014-07-24T12:34:06+01:01""#.to_owned())
1223        );
1224        assert_eq!(
1225            serde_json::to_string(
1226                &FixedOffset::east_opt(3650)
1227                    .unwrap()
1228                    .with_ymd_and_hms(2014, 7, 24, 12, 34, 6)
1229                    .unwrap()
1230            )
1231            .ok(),
1232            // An offset with seconds is not allowed by RFC 3339, so we round it to the nearest minute.
1233            // In this case `+01:00:50` becomes `+01:01`
1234            Some(r#""2014-07-24T12:34:06+01:01""#.to_owned())
1235        );
1236    }
1237
1238    #[test]
1239    fn test_serde_deserialize() {
1240        // should check against the offset as well (the normal DateTime comparison will ignore them)
1241        fn norm<Tz: TimeZone>(dt: &Option<DateTime<Tz>>) -> Option<(&DateTime<Tz>, &Tz::Offset)> {
1242            dt.as_ref().map(|dt| (dt, dt.offset()))
1243        }
1244
1245        let dt: Option<DateTime<Utc>> = serde_json::from_str(r#""2014-07-24T12:34:06Z""#).ok();
1246        assert_eq!(norm(&dt), norm(&Some(Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap())));
1247        let dt: Option<DateTime<Utc>> = serde_json::from_str(r#""2014-07-24T13:57:06+01:23""#).ok();
1248        assert_eq!(norm(&dt), norm(&Some(Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap())));
1249
1250        let dt: Option<DateTime<FixedOffset>> =
1251            serde_json::from_str(r#""2014-07-24T12:34:06Z""#).ok();
1252        assert_eq!(
1253            norm(&dt),
1254            norm(&Some(
1255                FixedOffset::east_opt(0).unwrap().with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()
1256            ))
1257        );
1258        let dt: Option<DateTime<FixedOffset>> =
1259            serde_json::from_str(r#""2014-07-24T13:57:06+01:23""#).ok();
1260        assert_eq!(
1261            norm(&dt),
1262            norm(&Some(
1263                FixedOffset::east_opt(60 * 60 + 23 * 60)
1264                    .unwrap()
1265                    .with_ymd_and_hms(2014, 7, 24, 13, 57, 6)
1266                    .unwrap()
1267            ))
1268        );
1269
1270        // we don't know the exact local offset but we can check that
1271        // the conversion didn't change the instant itself
1272        #[cfg(feature = "clock")]
1273        {
1274            let dt: DateTime<Local> =
1275                serde_json::from_str(r#""2014-07-24T12:34:06Z""#).expect("local should parse");
1276            assert_eq!(dt, Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap());
1277
1278            let dt: DateTime<Local> = serde_json::from_str(r#""2014-07-24T13:57:06+01:23""#)
1279                .expect("local should parse with offset");
1280            assert_eq!(dt, Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap());
1281        }
1282
1283        assert!(serde_json::from_str::<DateTime<Utc>>(r#""2014-07-32T12:34:06Z""#).is_err());
1284        assert!(
1285            serde_json::from_str::<DateTime<FixedOffset>>(r#""2014-07-32T12:34:06Z""#).is_err()
1286        );
1287    }
1288
1289    #[test]
1290    fn test_serde_bincode() {
1291        // Bincode is relevant to test separately from JSON because
1292        // it is not self-describing.
1293        use bincode::{deserialize, serialize};
1294
1295        let dt = Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap();
1296        let encoded = serialize(&dt).unwrap();
1297        let decoded: DateTime<Utc> = deserialize(&encoded).unwrap();
1298        assert_eq!(dt, decoded);
1299        assert_eq!(dt.offset(), decoded.offset());
1300    }
1301
1302    #[test]
1303    fn test_serde_no_offset_debug() {
1304        use crate::{MappedLocalTime, NaiveDate, NaiveDateTime, Offset};
1305        use core::fmt::Debug;
1306
1307        #[derive(Clone)]
1308        struct TestTimeZone;
1309        impl Debug for TestTimeZone {
1310            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1311                write!(f, "TEST")
1312            }
1313        }
1314        impl TimeZone for TestTimeZone {
1315            type Offset = TestTimeZone;
1316            fn from_offset(_state: &TestTimeZone) -> TestTimeZone {
1317                TestTimeZone
1318            }
1319            fn offset_from_local_date(&self, _local: &NaiveDate) -> MappedLocalTime<TestTimeZone> {
1320                MappedLocalTime::Single(TestTimeZone)
1321            }
1322            fn offset_from_local_datetime(
1323                &self,
1324                _local: &NaiveDateTime,
1325            ) -> MappedLocalTime<TestTimeZone> {
1326                MappedLocalTime::Single(TestTimeZone)
1327            }
1328            fn offset_from_utc_date(&self, _utc: &NaiveDate) -> TestTimeZone {
1329                TestTimeZone
1330            }
1331            fn offset_from_utc_datetime(&self, _utc: &NaiveDateTime) -> TestTimeZone {
1332                TestTimeZone
1333            }
1334        }
1335        impl Offset for TestTimeZone {
1336            fn fix(&self) -> FixedOffset {
1337                FixedOffset::east_opt(15 * 60 * 60).unwrap()
1338            }
1339        }
1340
1341        let tz = TestTimeZone;
1342        assert_eq!(format!("{:?}", &tz), "TEST");
1343
1344        let dt = tz.with_ymd_and_hms(2023, 4, 24, 21, 10, 33).unwrap();
1345        let encoded = serde_json::to_string(&dt).unwrap();
1346        dbg!(&encoded);
1347        let decoded: DateTime<FixedOffset> = serde_json::from_str(&encoded).unwrap();
1348        assert_eq!(dt, decoded);
1349        assert_eq!(dt.offset().fix(), *decoded.offset());
1350    }
1351}