1macro_rules! item {
10 ($seq:expr, $name:literal) => {
11 $seq.next_element()?
12 .ok_or_else(|| <A::Error as serde_core::de::Error>::custom(concat!("expected ", $name)))
13 };
14}
15
16#[cfg(any(feature = "formatting", feature = "parsing"))]
17pub mod iso8601;
18#[cfg(any(feature = "formatting", feature = "parsing"))]
19pub mod rfc2822;
20#[cfg(any(feature = "formatting", feature = "parsing"))]
21pub mod rfc3339;
22pub mod timestamp;
23mod visitor;
24
25#[cfg(feature = "serde-human-readable")]
26use alloc::string::ToString;
27use core::marker::PhantomData;
28
29#[cfg(feature = "serde-human-readable")]
30use serde_core::ser::Error as _;
31use serde_core::{Deserialize, Deserializer, Serialize, Serializer};
32#[cfg_attr(
42 all(feature = "formatting", feature = "parsing"),
43 doc = "[`Formattable`](crate::formatting::Formattable) and \
44 [`Parsable`](crate::parsing::Parsable)."
45)]
46#[cfg_attr(
47 all(feature = "formatting", not(feature = "parsing")),
48 doc = "[`Formattable`](crate::formatting::Formattable)."
49)]
50#[cfg_attr(
51 all(not(feature = "formatting"), feature = "parsing"),
52 doc = "[`Parsable`](crate::parsing::Parsable)."
53)]
54#[cfg_attr(
74 all(feature = "formatting", feature = "parsing"),
75 doc = "use ::serde::{Serialize, Deserialize};"
76)]
77#[cfg_attr(
78 all(feature = "formatting", not(feature = "parsing")),
79 doc = "use ::serde::Serialize;"
80)]
81#[cfg_attr(
82 all(not(feature = "formatting"), feature = "parsing"),
83 doc = "use ::serde::Deserialize;"
84)]
85#[cfg_attr(
92 all(feature = "formatting", feature = "parsing"),
93 doc = "#[derive(Serialize, Deserialize)]"
94)]
95#[cfg_attr(
96 all(feature = "formatting", not(feature = "parsing")),
97 doc = "#[derive(Serialize)]"
98)]
99#[cfg_attr(
100 all(not(feature = "formatting"), feature = "parsing"),
101 doc = "#[derive(Deserialize)]"
102)]
103#[cfg_attr(
115 all(feature = "formatting", feature = "parsing"),
116 doc = "use ::serde::{Serialize, Deserialize};"
117)]
118#[cfg_attr(
119 all(feature = "formatting", not(feature = "parsing")),
120 doc = "use ::serde::Serialize;"
121)]
122#[cfg_attr(
123 all(not(feature = "formatting"), feature = "parsing"),
124 doc = "use ::serde::Deserialize;"
125)]
126#[cfg_attr(
138 all(feature = "formatting", feature = "parsing"),
139 doc = "#[derive(Serialize, Deserialize)]"
140)]
141#[cfg_attr(
142 all(feature = "formatting", not(feature = "parsing")),
143 doc = "#[derive(Serialize)]"
144)]
145#[cfg_attr(
146 all(not(feature = "formatting"), feature = "parsing"),
147 doc = "#[derive(Deserialize)]"
148)]
149#[cfg_attr(
166 all(feature = "formatting", feature = "parsing"),
167 doc = "use ::serde::{Serialize, Deserialize};"
168)]
169#[cfg_attr(
170 all(feature = "formatting", not(feature = "parsing")),
171 doc = "use ::serde::Serialize;"
172)]
173#[cfg_attr(
174 all(not(feature = "formatting"), feature = "parsing"),
175 doc = "use ::serde::Deserialize;"
176)]
177#[cfg_attr(
192 all(feature = "formatting", feature = "parsing"),
193 doc = "#[derive(Serialize, Deserialize)]"
194)]
195#[cfg_attr(
196 all(feature = "formatting", not(feature = "parsing")),
197 doc = "#[derive(Serialize)]"
198)]
199#[cfg_attr(
200 all(not(feature = "formatting"), feature = "parsing"),
201 doc = "#[derive(Deserialize)]"
202)]
203#[cfg(all(feature = "macros", any(feature = "formatting", feature = "parsing")))]
214pub use time_macros::serde_format_description as format_description;
215
216use self::visitor::Visitor;
217#[cfg(feature = "parsing")]
218use crate::format_description::{BorrowedFormatItem, Component, StaticFormatDescription, modifier};
219use crate::{
220 Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcDateTime, UtcOffset, Weekday,
221};
222
223#[cfg(feature = "parsing")]
225const DATE_FORMAT: StaticFormatDescription = &[
226 #[cfg(feature = "large-dates")]
227 BorrowedFormatItem::Component(Component::CalendarYearFullExtendedRange(
228 modifier::CalendarYearFullExtendedRange::default(),
229 )),
230 #[cfg(not(feature = "large-dates"))]
231 BorrowedFormatItem::Component(Component::CalendarYearFullStandardRange(
232 modifier::CalendarYearFullStandardRange::default(),
233 )),
234 BorrowedFormatItem::StringLiteral("-"),
235 BorrowedFormatItem::Component(Component::MonthNumerical(
236 modifier::MonthNumerical::default(),
237 )),
238 BorrowedFormatItem::StringLiteral("-"),
239 BorrowedFormatItem::Component(Component::Day(modifier::Day::default())),
240];
241
242impl Serialize for Date {
243 #[inline]
244 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
245 where
246 S: Serializer,
247 {
248 #[cfg(feature = "serde-human-readable")]
249 if serializer.is_human_readable() {
250 let Ok(s) = self.format(&DATE_FORMAT) else {
251 return Err(S::Error::custom("failed formatting `Date`"));
252 };
253 return serializer.serialize_str(&s);
254 }
255
256 (self.year(), self.ordinal()).serialize(serializer)
257 }
258}
259
260impl<'a> Deserialize<'a> for Date {
261 #[inline]
262 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
263 where
264 D: Deserializer<'a>,
265 {
266 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
267 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
268 } else {
269 deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
270 }
271 }
272}
273
274impl Serialize for Duration {
275 #[inline]
276 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
277 where
278 S: Serializer,
279 {
280 #[cfg(feature = "serde-human-readable")]
281 if serializer.is_human_readable() {
282 return serializer.collect_str(&format_args!(
283 "{}{}.{:>09}",
284 if self.is_negative() { "-" } else { "" },
285 self.whole_seconds().unsigned_abs(),
286 self.subsec_nanoseconds().abs(),
287 ));
288 }
289
290 (self.whole_seconds(), self.subsec_nanoseconds()).serialize(serializer)
291 }
292}
293
294impl<'a> Deserialize<'a> for Duration {
295 #[inline]
296 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
297 where
298 D: Deserializer<'a>,
299 {
300 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
301 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
302 } else {
303 deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
304 }
305 }
306}
307
308#[cfg(feature = "parsing")]
310const OFFSET_DATE_TIME_FORMAT: StaticFormatDescription = &[
311 BorrowedFormatItem::Compound(DATE_FORMAT),
312 BorrowedFormatItem::StringLiteral(" "),
313 BorrowedFormatItem::Compound(TIME_FORMAT),
314 BorrowedFormatItem::StringLiteral(" "),
315 BorrowedFormatItem::Compound(UTC_OFFSET_FORMAT),
316];
317
318impl Serialize for OffsetDateTime {
319 #[inline]
320 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
321 where
322 S: Serializer,
323 {
324 #[cfg(feature = "serde-human-readable")]
325 if serializer.is_human_readable() {
326 let Ok(s) = self.format(&OFFSET_DATE_TIME_FORMAT) else {
327 return Err(S::Error::custom("failed formatting `OffsetDateTime`"));
328 };
329 return serializer.serialize_str(&s);
330 }
331
332 (
333 self.year(),
334 self.ordinal(),
335 self.hour(),
336 self.minute(),
337 self.second(),
338 self.nanosecond(),
339 self.offset().whole_hours(),
340 self.offset().minutes_past_hour(),
341 self.offset().seconds_past_minute(),
342 )
343 .serialize(serializer)
344 }
345}
346
347impl<'a> Deserialize<'a> for OffsetDateTime {
348 #[inline]
349 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
350 where
351 D: Deserializer<'a>,
352 {
353 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
354 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
355 } else {
356 deserializer.deserialize_tuple(9, Visitor::<Self>(PhantomData))
357 }
358 }
359}
360
361#[cfg(feature = "parsing")]
363const PRIMITIVE_DATE_TIME_FORMAT: StaticFormatDescription = &[
364 BorrowedFormatItem::Compound(DATE_FORMAT),
365 BorrowedFormatItem::StringLiteral(" "),
366 BorrowedFormatItem::Compound(TIME_FORMAT),
367];
368
369impl Serialize for PrimitiveDateTime {
370 #[inline]
371 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
372 where
373 S: Serializer,
374 {
375 #[cfg(feature = "serde-human-readable")]
376 if serializer.is_human_readable() {
377 let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else {
378 return Err(S::Error::custom("failed formatting `PrimitiveDateTime`"));
379 };
380 return serializer.serialize_str(&s);
381 }
382
383 (
384 self.year(),
385 self.ordinal(),
386 self.hour(),
387 self.minute(),
388 self.second(),
389 self.nanosecond(),
390 )
391 .serialize(serializer)
392 }
393}
394
395impl<'a> Deserialize<'a> for PrimitiveDateTime {
396 #[inline]
397 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
398 where
399 D: Deserializer<'a>,
400 {
401 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
402 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
403 } else {
404 deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
405 }
406 }
407}
408
409#[cfg(feature = "parsing")]
411const UTC_DATE_TIME_FORMAT: StaticFormatDescription = PRIMITIVE_DATE_TIME_FORMAT;
412
413impl Serialize for UtcDateTime {
414 #[inline]
415 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
416 where
417 S: Serializer,
418 {
419 #[cfg(feature = "serde-human-readable")]
420 if serializer.is_human_readable() {
421 let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else {
422 return Err(S::Error::custom("failed formatting `UtcDateTime`"));
423 };
424 return serializer.serialize_str(&s);
425 }
426
427 (
428 self.year(),
429 self.ordinal(),
430 self.hour(),
431 self.minute(),
432 self.second(),
433 self.nanosecond(),
434 )
435 .serialize(serializer)
436 }
437}
438
439impl<'a> Deserialize<'a> for UtcDateTime {
440 #[inline]
441 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
442 where
443 D: Deserializer<'a>,
444 {
445 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
446 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
447 } else {
448 deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
449 }
450 }
451}
452
453#[cfg(feature = "parsing")]
455const TIME_FORMAT: StaticFormatDescription = &[
456 BorrowedFormatItem::Component(Component::Hour24(modifier::Hour24::default())),
457 BorrowedFormatItem::StringLiteral(":"),
458 BorrowedFormatItem::Component(Component::Minute(modifier::Minute::default())),
459 BorrowedFormatItem::StringLiteral(":"),
460 BorrowedFormatItem::Component(Component::Second(modifier::Second::default())),
461 BorrowedFormatItem::StringLiteral("."),
462 BorrowedFormatItem::Component(Component::Subsecond(modifier::Subsecond::default())),
463];
464
465impl Serialize for Time {
466 #[inline]
467 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
468 where
469 S: Serializer,
470 {
471 #[cfg(feature = "serde-human-readable")]
472 if serializer.is_human_readable() {
473 let Ok(s) = self.format(&TIME_FORMAT) else {
474 return Err(S::Error::custom("failed formatting `Time`"));
475 };
476 return serializer.serialize_str(&s);
477 }
478
479 (self.hour(), self.minute(), self.second(), self.nanosecond()).serialize(serializer)
480 }
481}
482
483impl<'a> Deserialize<'a> for Time {
484 #[inline]
485 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
486 where
487 D: Deserializer<'a>,
488 {
489 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
490 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
491 } else {
492 deserializer.deserialize_tuple(4, Visitor::<Self>(PhantomData))
493 }
494 }
495}
496
497#[cfg(feature = "parsing")]
499const UTC_OFFSET_FORMAT: StaticFormatDescription = &[
500 BorrowedFormatItem::Component(Component::OffsetHour(
501 const {
502 let mut m = modifier::OffsetHour::default();
503 m.sign_is_mandatory = true;
504 m
505 },
506 )),
507 BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
508 BorrowedFormatItem::StringLiteral(":"),
509 BorrowedFormatItem::Component(Component::OffsetMinute(
510 const { modifier::OffsetMinute::default() },
511 )),
512 BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
513 BorrowedFormatItem::StringLiteral(":"),
514 BorrowedFormatItem::Component(Component::OffsetSecond(
515 const { modifier::OffsetSecond::default() },
516 )),
517 ])),
518 ])),
519];
520
521impl Serialize for UtcOffset {
522 #[inline]
523 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
524 where
525 S: Serializer,
526 {
527 #[cfg(feature = "serde-human-readable")]
528 if serializer.is_human_readable() {
529 let Ok(s) = self.format(&UTC_OFFSET_FORMAT) else {
530 return Err(S::Error::custom("failed formatting `UtcOffset`"));
531 };
532 return serializer.serialize_str(&s);
533 }
534
535 (
536 self.whole_hours(),
537 self.minutes_past_hour(),
538 self.seconds_past_minute(),
539 )
540 .serialize(serializer)
541 }
542}
543
544impl<'a> Deserialize<'a> for UtcOffset {
545 #[inline]
546 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
547 where
548 D: Deserializer<'a>,
549 {
550 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
551 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
552 } else {
553 deserializer.deserialize_tuple(3, Visitor::<Self>(PhantomData))
554 }
555 }
556}
557
558impl Serialize for Weekday {
559 #[inline]
560 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
561 where
562 S: Serializer,
563 {
564 #[cfg(feature = "serde-human-readable")]
565 if serializer.is_human_readable() {
566 #[cfg(not(feature = "std"))]
567 use alloc::string::ToString;
568 return self.to_string().serialize(serializer);
569 }
570
571 self.number_from_monday().serialize(serializer)
572 }
573}
574
575impl<'a> Deserialize<'a> for Weekday {
576 #[inline]
577 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
578 where
579 D: Deserializer<'a>,
580 {
581 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
582 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
583 } else {
584 deserializer.deserialize_u8(Visitor::<Self>(PhantomData))
585 }
586 }
587}
588
589impl Serialize for Month {
590 #[inline]
591 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
592 where
593 S: Serializer,
594 {
595 #[cfg(feature = "serde-human-readable")]
596 if serializer.is_human_readable() {
597 #[cfg(not(feature = "std"))]
598 use alloc::string::String;
599 return self.to_string().serialize(serializer);
600 }
601
602 u8::from(*self).serialize(serializer)
603 }
604}
605
606impl<'a> Deserialize<'a> for Month {
607 #[inline]
608 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
609 where
610 D: Deserializer<'a>,
611 {
612 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
613 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
614 } else {
615 deserializer.deserialize_u8(Visitor::<Self>(PhantomData))
616 }
617 }
618}