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(
49 all(feature = "formatting", feature = "parsing"),
50 doc = "[`Formattable`](crate::formatting::Formattable) and \
51 [`Parsable`](crate::parsing::Parsable)."
52)]
53#[cfg_attr(
54 all(feature = "formatting", not(feature = "parsing")),
55 doc = "[`Formattable`](crate::formatting::Formattable)."
56)]
57#[cfg_attr(
58 all(not(feature = "formatting"), feature = "parsing"),
59 doc = "[`Parsable`](crate::parsing::Parsable)."
60)]
61#[cfg_attr(
89 all(feature = "formatting", feature = "parsing"),
90 doc = "use ::serde::{Serialize, Deserialize};"
91)]
92#[cfg_attr(
93 all(feature = "formatting", not(feature = "parsing")),
94 doc = "use ::serde::Serialize;"
95)]
96#[cfg_attr(
97 all(not(feature = "formatting"), feature = "parsing"),
98 doc = "use ::serde::Deserialize;"
99)]
100#[cfg_attr(
107 all(feature = "formatting", feature = "parsing"),
108 doc = "#[derive(Serialize, Deserialize)]"
109)]
110#[cfg_attr(
111 all(feature = "formatting", not(feature = "parsing")),
112 doc = "#[derive(Serialize)]"
113)]
114#[cfg_attr(
115 all(not(feature = "formatting"), feature = "parsing"),
116 doc = "#[derive(Deserialize)]"
117)]
118#[cfg_attr(
130 all(feature = "formatting", feature = "parsing"),
131 doc = "use ::serde::{Serialize, Deserialize};"
132)]
133#[cfg_attr(
134 all(feature = "formatting", not(feature = "parsing")),
135 doc = "use ::serde::Serialize;"
136)]
137#[cfg_attr(
138 all(not(feature = "formatting"), feature = "parsing"),
139 doc = "use ::serde::Deserialize;"
140)]
141#[cfg_attr(
153 all(feature = "formatting", feature = "parsing"),
154 doc = "#[derive(Serialize, Deserialize)]"
155)]
156#[cfg_attr(
157 all(feature = "formatting", not(feature = "parsing")),
158 doc = "#[derive(Serialize)]"
159)]
160#[cfg_attr(
161 all(not(feature = "formatting"), feature = "parsing"),
162 doc = "#[derive(Deserialize)]"
163)]
164#[cfg_attr(
181 all(feature = "formatting", feature = "parsing"),
182 doc = "use ::serde::{Serialize, Deserialize};"
183)]
184#[cfg_attr(
185 all(feature = "formatting", not(feature = "parsing")),
186 doc = "use ::serde::Serialize;"
187)]
188#[cfg_attr(
189 all(not(feature = "formatting"), feature = "parsing"),
190 doc = "use ::serde::Deserialize;"
191)]
192#[cfg_attr(
207 all(feature = "formatting", feature = "parsing"),
208 doc = "#[derive(Serialize, Deserialize)]"
209)]
210#[cfg_attr(
211 all(feature = "formatting", not(feature = "parsing")),
212 doc = "#[derive(Serialize)]"
213)]
214#[cfg_attr(
215 all(not(feature = "formatting"), feature = "parsing"),
216 doc = "#[derive(Deserialize)]"
217)]
218#[cfg(all(feature = "macros", any(feature = "formatting", feature = "parsing")))]
229pub use time_macros::serde_format_description as format_description;
230
231use self::visitor::Visitor;
232#[cfg(feature = "parsing")]
233use crate::format_description::__private::FormatDescriptionV3Inner;
234#[cfg(feature = "parsing")]
235use crate::format_description::{FormatDescriptionV3, modifier};
236use crate::{
237 Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, Timestamp, UtcDateTime,
238 UtcOffset, Weekday,
239};
240
241#[cfg(feature = "parsing")]
243const DATE_FORMAT: FormatDescriptionV3<'_> = FormatDescriptionV3Inner::BorrowedCompound(&[
244 #[cfg(feature = "large-dates")]
245 FormatDescriptionV3Inner::CalendarYearFullExtendedRange(
246 modifier::CalendarYearFullExtendedRange::default(),
247 ),
248 #[cfg(not(feature = "large-dates"))]
249 FormatDescriptionV3Inner::CalendarYearFullStandardRange(
250 modifier::CalendarYearFullStandardRange::default(),
251 ),
252 FormatDescriptionV3Inner::BorrowedLiteral("-"),
253 FormatDescriptionV3Inner::MonthNumerical(modifier::MonthNumerical::default()),
254 FormatDescriptionV3Inner::BorrowedLiteral("-"),
255 FormatDescriptionV3Inner::Day(modifier::Day::default()),
256])
257.into_opaque();
258
259impl Serialize for Date {
260 #[inline]
261 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
262 where
263 S: Serializer,
264 {
265 #[cfg(feature = "serde-human-readable")]
266 if serializer.is_human_readable() {
267 let Ok(s) = self.format(&DATE_FORMAT) else {
268 return Err(S::Error::custom("failed formatting `Date`"));
269 };
270 return serializer.serialize_str(&s);
271 }
272
273 (self.year(), self.ordinal()).serialize(serializer)
274 }
275}
276
277impl<'a> Deserialize<'a> for Date {
278 #[inline]
279 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
280 where
281 D: Deserializer<'a>,
282 {
283 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
284 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
285 } else {
286 deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
287 }
288 }
289}
290
291impl Serialize for Duration {
292 #[inline]
293 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
294 where
295 S: Serializer,
296 {
297 #[cfg(feature = "serde-human-readable")]
298 if serializer.is_human_readable() {
299 return serializer.collect_str(&format_args!(
300 "{}{}.{:>09}",
301 if self.is_negative() { "-" } else { "" },
302 self.whole_seconds().unsigned_abs(),
303 self.subsec_nanoseconds().abs(),
304 ));
305 }
306
307 (self.whole_seconds(), self.subsec_nanoseconds()).serialize(serializer)
308 }
309}
310
311impl<'a> Deserialize<'a> for Duration {
312 #[inline]
313 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
314 where
315 D: Deserializer<'a>,
316 {
317 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
318 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
319 } else {
320 deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
321 }
322 }
323}
324
325#[cfg(feature = "parsing")]
327const OFFSET_DATE_TIME_FORMAT: FormatDescriptionV3<'_> =
328 FormatDescriptionV3Inner::BorrowedCompound(&[
329 #[cfg(feature = "large-dates")]
330 FormatDescriptionV3Inner::CalendarYearFullExtendedRange(
331 modifier::CalendarYearFullExtendedRange::default(),
332 ),
333 #[cfg(not(feature = "large-dates"))]
334 FormatDescriptionV3Inner::CalendarYearFullStandardRange(
335 modifier::CalendarYearFullStandardRange::default(),
336 ),
337 FormatDescriptionV3Inner::BorrowedLiteral("-"),
338 FormatDescriptionV3Inner::MonthNumerical(modifier::MonthNumerical::default()),
339 FormatDescriptionV3Inner::BorrowedLiteral("-"),
340 FormatDescriptionV3Inner::Day(modifier::Day::default()),
341 FormatDescriptionV3Inner::BorrowedLiteral(" "),
342 FormatDescriptionV3Inner::Hour24(modifier::Hour24::default()),
343 FormatDescriptionV3Inner::BorrowedLiteral(":"),
344 FormatDescriptionV3Inner::Minute(modifier::Minute::default()),
345 FormatDescriptionV3Inner::BorrowedLiteral(":"),
346 FormatDescriptionV3Inner::Second(modifier::Second::default()),
347 FormatDescriptionV3Inner::BorrowedLiteral("."),
348 FormatDescriptionV3Inner::Subsecond(modifier::Subsecond::default()),
349 FormatDescriptionV3Inner::BorrowedLiteral(" "),
350 FormatDescriptionV3Inner::OffsetHour(
351 modifier::OffsetHour::default().with_sign_is_mandatory(true),
352 ),
353 FormatDescriptionV3Inner::BorrowedLiteral(":"),
354 FormatDescriptionV3Inner::OffsetMinute(modifier::OffsetMinute::default()),
355 FormatDescriptionV3Inner::BorrowedLiteral(":"),
356 FormatDescriptionV3Inner::OffsetSecond(modifier::OffsetSecond::default()),
357 ])
358 .into_opaque();
359
360impl Serialize for OffsetDateTime {
361 #[inline]
362 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
363 where
364 S: Serializer,
365 {
366 #[cfg(feature = "serde-human-readable")]
367 if serializer.is_human_readable() {
368 let Ok(s) = self.format(&OFFSET_DATE_TIME_FORMAT) else {
369 return Err(S::Error::custom("failed formatting `OffsetDateTime`"));
370 };
371 return serializer.serialize_str(&s);
372 }
373
374 (
375 self.year(),
376 self.ordinal(),
377 self.hour(),
378 self.minute(),
379 self.second(),
380 self.nanosecond(),
381 self.offset().whole_hours(),
382 self.offset().minutes_past_hour(),
383 self.offset().seconds_past_minute(),
384 )
385 .serialize(serializer)
386 }
387}
388
389impl<'a> Deserialize<'a> for OffsetDateTime {
390 #[inline]
391 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
392 where
393 D: Deserializer<'a>,
394 {
395 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
396 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
397 } else {
398 deserializer.deserialize_tuple(9, Visitor::<Self>(PhantomData))
399 }
400 }
401}
402
403#[cfg(feature = "parsing")]
405const PRIMITIVE_DATE_TIME_FORMAT: FormatDescriptionV3<'_> =
406 FormatDescriptionV3Inner::BorrowedCompound(&[
407 #[cfg(feature = "large-dates")]
408 FormatDescriptionV3Inner::CalendarYearFullExtendedRange(
409 modifier::CalendarYearFullExtendedRange::default(),
410 ),
411 #[cfg(not(feature = "large-dates"))]
412 FormatDescriptionV3Inner::CalendarYearFullStandardRange(
413 modifier::CalendarYearFullStandardRange::default(),
414 ),
415 FormatDescriptionV3Inner::BorrowedLiteral("-"),
416 FormatDescriptionV3Inner::MonthNumerical(modifier::MonthNumerical::default()),
417 FormatDescriptionV3Inner::BorrowedLiteral("-"),
418 FormatDescriptionV3Inner::Day(modifier::Day::default()),
419 FormatDescriptionV3Inner::BorrowedLiteral(" "),
420 FormatDescriptionV3Inner::Hour24(modifier::Hour24::default()),
421 FormatDescriptionV3Inner::BorrowedLiteral(":"),
422 FormatDescriptionV3Inner::Minute(modifier::Minute::default()),
423 FormatDescriptionV3Inner::BorrowedLiteral(":"),
424 FormatDescriptionV3Inner::Second(modifier::Second::default()),
425 FormatDescriptionV3Inner::BorrowedLiteral("."),
426 FormatDescriptionV3Inner::Subsecond(modifier::Subsecond::default()),
427 ])
428 .into_opaque();
429
430impl Serialize for PrimitiveDateTime {
431 #[inline]
432 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
433 where
434 S: Serializer,
435 {
436 #[cfg(feature = "serde-human-readable")]
437 if serializer.is_human_readable() {
438 let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else {
439 return Err(S::Error::custom("failed formatting `PrimitiveDateTime`"));
440 };
441 return serializer.serialize_str(&s);
442 }
443
444 (
445 self.year(),
446 self.ordinal(),
447 self.hour(),
448 self.minute(),
449 self.second(),
450 self.nanosecond(),
451 )
452 .serialize(serializer)
453 }
454}
455
456impl<'a> Deserialize<'a> for PrimitiveDateTime {
457 #[inline]
458 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
459 where
460 D: Deserializer<'a>,
461 {
462 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
463 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
464 } else {
465 deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
466 }
467 }
468}
469
470#[cfg(feature = "parsing")]
472const UTC_DATE_TIME_FORMAT: FormatDescriptionV3<'_> = PRIMITIVE_DATE_TIME_FORMAT;
473
474impl Serialize for UtcDateTime {
475 #[inline]
476 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
477 where
478 S: Serializer,
479 {
480 #[cfg(feature = "serde-human-readable")]
481 if serializer.is_human_readable() {
482 let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else {
483 return Err(S::Error::custom("failed formatting `UtcDateTime`"));
484 };
485 return serializer.serialize_str(&s);
486 }
487
488 (
489 self.year(),
490 self.ordinal(),
491 self.hour(),
492 self.minute(),
493 self.second(),
494 self.nanosecond(),
495 )
496 .serialize(serializer)
497 }
498}
499
500impl<'a> Deserialize<'a> for UtcDateTime {
501 #[inline]
502 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
503 where
504 D: Deserializer<'a>,
505 {
506 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
507 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
508 } else {
509 deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
510 }
511 }
512}
513
514#[cfg(feature = "parsing")]
516const TIME_FORMAT: FormatDescriptionV3<'_> = FormatDescriptionV3Inner::BorrowedCompound(&[
517 FormatDescriptionV3Inner::Hour24(modifier::Hour24::default()),
518 FormatDescriptionV3Inner::BorrowedLiteral(":"),
519 FormatDescriptionV3Inner::Minute(modifier::Minute::default()),
520 FormatDescriptionV3Inner::BorrowedLiteral(":"),
521 FormatDescriptionV3Inner::Second(modifier::Second::default()),
522 FormatDescriptionV3Inner::BorrowedLiteral("."),
523 FormatDescriptionV3Inner::Subsecond(modifier::Subsecond::default()),
524])
525.into_opaque();
526
527impl Serialize for Time {
528 #[inline]
529 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
530 where
531 S: Serializer,
532 {
533 #[cfg(feature = "serde-human-readable")]
534 if serializer.is_human_readable() {
535 let Ok(s) = self.format(&TIME_FORMAT) else {
536 return Err(S::Error::custom("failed formatting `Time`"));
537 };
538 return serializer.serialize_str(&s);
539 }
540
541 (self.hour(), self.minute(), self.second(), self.nanosecond()).serialize(serializer)
542 }
543}
544
545impl<'a> Deserialize<'a> for Time {
546 #[inline]
547 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
548 where
549 D: Deserializer<'a>,
550 {
551 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
552 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
553 } else {
554 deserializer.deserialize_tuple(4, Visitor::<Self>(PhantomData))
555 }
556 }
557}
558
559#[cfg(feature = "parsing")]
561const UTC_OFFSET_FORMAT: FormatDescriptionV3<'_> = FormatDescriptionV3Inner::BorrowedCompound(&[
562 FormatDescriptionV3Inner::OffsetHour(
563 modifier::OffsetHour::default().with_sign_is_mandatory(true),
564 ),
565 FormatDescriptionV3Inner::BorrowedLiteral(":"),
566 FormatDescriptionV3Inner::OffsetMinute(modifier::OffsetMinute::default()),
567 FormatDescriptionV3Inner::BorrowedLiteral(":"),
568 FormatDescriptionV3Inner::OffsetSecond(modifier::OffsetSecond::default()),
569])
570.into_opaque();
571
572impl Serialize for UtcOffset {
573 #[inline]
574 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
575 where
576 S: Serializer,
577 {
578 #[cfg(feature = "serde-human-readable")]
579 if serializer.is_human_readable() {
580 let Ok(s) = self.format(&UTC_OFFSET_FORMAT) else {
581 return Err(S::Error::custom("failed formatting `UtcOffset`"));
582 };
583 return serializer.serialize_str(&s);
584 }
585
586 (
587 self.whole_hours(),
588 self.minutes_past_hour(),
589 self.seconds_past_minute(),
590 )
591 .serialize(serializer)
592 }
593}
594
595impl<'a> Deserialize<'a> for UtcOffset {
596 #[inline]
597 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
598 where
599 D: Deserializer<'a>,
600 {
601 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
602 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
603 } else {
604 deserializer.deserialize_tuple(3, Visitor::<Self>(PhantomData))
605 }
606 }
607}
608
609impl Serialize for Timestamp {
610 #[inline]
611 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
612 where
613 S: Serializer,
614 {
615 self.as_nanoseconds().serialize(serializer)
616 }
617}
618
619impl<'a> Deserialize<'a> for Timestamp {
620 #[inline]
621 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
622 where
623 D: Deserializer<'a>,
624 {
625 deserializer.deserialize_i128(Visitor::<Self>(PhantomData))
626 }
627}
628
629impl Serialize for Weekday {
630 #[inline]
631 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
632 where
633 S: Serializer,
634 {
635 #[cfg(feature = "serde-human-readable")]
636 if serializer.is_human_readable() {
637 #[cfg(not(feature = "std"))]
638 use alloc::string::ToString;
639 return self.to_string().serialize(serializer);
640 }
641
642 self.number_from_monday().serialize(serializer)
643 }
644}
645
646impl<'a> Deserialize<'a> for Weekday {
647 #[inline]
648 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
649 where
650 D: Deserializer<'a>,
651 {
652 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
653 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
654 } else {
655 deserializer.deserialize_u8(Visitor::<Self>(PhantomData))
656 }
657 }
658}
659
660impl Serialize for Month {
661 #[inline]
662 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
663 where
664 S: Serializer,
665 {
666 #[cfg(feature = "serde-human-readable")]
667 if serializer.is_human_readable() {
668 #[cfg(not(feature = "std"))]
669 use alloc::string::String;
670 return self.to_string().serialize(serializer);
671 }
672
673 u8::from(*self).serialize(serializer)
674 }
675}
676
677impl<'a> Deserialize<'a> for Month {
678 #[inline]
679 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
680 where
681 D: Deserializer<'a>,
682 {
683 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
684 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
685 } else {
686 deserializer.deserialize_u8(Visitor::<Self>(PhantomData))
687 }
688 }
689}