/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 | | } |