Coverage Report

Created: 2025-07-23 06:18

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