chrono/naive/datetime/
serde.rs

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