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