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