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, UtcDateTime, UtcOffset, Weekday,
238};
239
240#[cfg(feature = "parsing")]
242const DATE_FORMAT: FormatDescriptionV3<'_> = FormatDescriptionV3Inner::BorrowedCompound(&[
243 #[cfg(feature = "large-dates")]
244 FormatDescriptionV3Inner::CalendarYearFullExtendedRange(
245 modifier::CalendarYearFullExtendedRange::default(),
246 ),
247 #[cfg(not(feature = "large-dates"))]
248 FormatDescriptionV3Inner::CalendarYearFullStandardRange(
249 modifier::CalendarYearFullStandardRange::default(),
250 ),
251 FormatDescriptionV3Inner::BorrowedLiteral("-"),
252 FormatDescriptionV3Inner::MonthNumerical(modifier::MonthNumerical::default()),
253 FormatDescriptionV3Inner::BorrowedLiteral("-"),
254 FormatDescriptionV3Inner::Day(modifier::Day::default()),
255])
256.into_opaque();
257
258impl Serialize for Date {
259 #[inline]
260 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
261 where
262 S: Serializer,
263 {
264 #[cfg(feature = "serde-human-readable")]
265 if serializer.is_human_readable() {
266 let Ok(s) = self.format(&DATE_FORMAT) else {
267 return Err(S::Error::custom("failed formatting `Date`"));
268 };
269 return serializer.serialize_str(&s);
270 }
271
272 (self.year(), self.ordinal()).serialize(serializer)
273 }
274}
275
276impl<'a> Deserialize<'a> for Date {
277 #[inline]
278 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
279 where
280 D: Deserializer<'a>,
281 {
282 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
283 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
284 } else {
285 deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
286 }
287 }
288}
289
290impl Serialize for Duration {
291 #[inline]
292 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
293 where
294 S: Serializer,
295 {
296 #[cfg(feature = "serde-human-readable")]
297 if serializer.is_human_readable() {
298 return serializer.collect_str(&format_args!(
299 "{}{}.{:>09}",
300 if self.is_negative() { "-" } else { "" },
301 self.whole_seconds().unsigned_abs(),
302 self.subsec_nanoseconds().abs(),
303 ));
304 }
305
306 (self.whole_seconds(), self.subsec_nanoseconds()).serialize(serializer)
307 }
308}
309
310impl<'a> Deserialize<'a> for Duration {
311 #[inline]
312 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
313 where
314 D: Deserializer<'a>,
315 {
316 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
317 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
318 } else {
319 deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
320 }
321 }
322}
323
324#[cfg(feature = "parsing")]
326const OFFSET_DATE_TIME_FORMAT: FormatDescriptionV3<'_> =
327 FormatDescriptionV3Inner::BorrowedCompound(&[
328 #[cfg(feature = "large-dates")]
329 FormatDescriptionV3Inner::CalendarYearFullExtendedRange(
330 modifier::CalendarYearFullExtendedRange::default(),
331 ),
332 #[cfg(not(feature = "large-dates"))]
333 FormatDescriptionV3Inner::CalendarYearFullStandardRange(
334 modifier::CalendarYearFullStandardRange::default(),
335 ),
336 FormatDescriptionV3Inner::BorrowedLiteral("-"),
337 FormatDescriptionV3Inner::MonthNumerical(modifier::MonthNumerical::default()),
338 FormatDescriptionV3Inner::BorrowedLiteral("-"),
339 FormatDescriptionV3Inner::Day(modifier::Day::default()),
340 FormatDescriptionV3Inner::BorrowedLiteral(" "),
341 FormatDescriptionV3Inner::Hour24(modifier::Hour24::default()),
342 FormatDescriptionV3Inner::BorrowedLiteral(":"),
343 FormatDescriptionV3Inner::Minute(modifier::Minute::default()),
344 FormatDescriptionV3Inner::BorrowedLiteral(":"),
345 FormatDescriptionV3Inner::Second(modifier::Second::default()),
346 FormatDescriptionV3Inner::BorrowedLiteral("."),
347 FormatDescriptionV3Inner::Subsecond(modifier::Subsecond::default()),
348 FormatDescriptionV3Inner::BorrowedLiteral(" "),
349 FormatDescriptionV3Inner::OffsetHour(
350 modifier::OffsetHour::default().with_sign_is_mandatory(true),
351 ),
352 FormatDescriptionV3Inner::BorrowedLiteral(":"),
353 FormatDescriptionV3Inner::OffsetMinute(modifier::OffsetMinute::default()),
354 FormatDescriptionV3Inner::BorrowedLiteral(":"),
355 FormatDescriptionV3Inner::OffsetSecond(modifier::OffsetSecond::default()),
356 ])
357 .into_opaque();
358
359impl Serialize for OffsetDateTime {
360 #[inline]
361 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
362 where
363 S: Serializer,
364 {
365 #[cfg(feature = "serde-human-readable")]
366 if serializer.is_human_readable() {
367 let Ok(s) = self.format(&OFFSET_DATE_TIME_FORMAT) else {
368 return Err(S::Error::custom("failed formatting `OffsetDateTime`"));
369 };
370 return serializer.serialize_str(&s);
371 }
372
373 (
374 self.year(),
375 self.ordinal(),
376 self.hour(),
377 self.minute(),
378 self.second(),
379 self.nanosecond(),
380 self.offset().whole_hours(),
381 self.offset().minutes_past_hour(),
382 self.offset().seconds_past_minute(),
383 )
384 .serialize(serializer)
385 }
386}
387
388impl<'a> Deserialize<'a> for OffsetDateTime {
389 #[inline]
390 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
391 where
392 D: Deserializer<'a>,
393 {
394 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
395 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
396 } else {
397 deserializer.deserialize_tuple(9, Visitor::<Self>(PhantomData))
398 }
399 }
400}
401
402#[cfg(feature = "parsing")]
404const PRIMITIVE_DATE_TIME_FORMAT: FormatDescriptionV3<'_> =
405 FormatDescriptionV3Inner::BorrowedCompound(&[
406 #[cfg(feature = "large-dates")]
407 FormatDescriptionV3Inner::CalendarYearFullExtendedRange(
408 modifier::CalendarYearFullExtendedRange::default(),
409 ),
410 #[cfg(not(feature = "large-dates"))]
411 FormatDescriptionV3Inner::CalendarYearFullStandardRange(
412 modifier::CalendarYearFullStandardRange::default(),
413 ),
414 FormatDescriptionV3Inner::BorrowedLiteral("-"),
415 FormatDescriptionV3Inner::MonthNumerical(modifier::MonthNumerical::default()),
416 FormatDescriptionV3Inner::BorrowedLiteral("-"),
417 FormatDescriptionV3Inner::Day(modifier::Day::default()),
418 FormatDescriptionV3Inner::BorrowedLiteral(" "),
419 FormatDescriptionV3Inner::Hour24(modifier::Hour24::default()),
420 FormatDescriptionV3Inner::BorrowedLiteral(":"),
421 FormatDescriptionV3Inner::Minute(modifier::Minute::default()),
422 FormatDescriptionV3Inner::BorrowedLiteral(":"),
423 FormatDescriptionV3Inner::Second(modifier::Second::default()),
424 FormatDescriptionV3Inner::BorrowedLiteral("."),
425 FormatDescriptionV3Inner::Subsecond(modifier::Subsecond::default()),
426 ])
427 .into_opaque();
428
429impl Serialize for PrimitiveDateTime {
430 #[inline]
431 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
432 where
433 S: Serializer,
434 {
435 #[cfg(feature = "serde-human-readable")]
436 if serializer.is_human_readable() {
437 let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else {
438 return Err(S::Error::custom("failed formatting `PrimitiveDateTime`"));
439 };
440 return serializer.serialize_str(&s);
441 }
442
443 (
444 self.year(),
445 self.ordinal(),
446 self.hour(),
447 self.minute(),
448 self.second(),
449 self.nanosecond(),
450 )
451 .serialize(serializer)
452 }
453}
454
455impl<'a> Deserialize<'a> for PrimitiveDateTime {
456 #[inline]
457 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
458 where
459 D: Deserializer<'a>,
460 {
461 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
462 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
463 } else {
464 deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
465 }
466 }
467}
468
469#[cfg(feature = "parsing")]
471const UTC_DATE_TIME_FORMAT: FormatDescriptionV3<'_> = PRIMITIVE_DATE_TIME_FORMAT;
472
473impl Serialize for UtcDateTime {
474 #[inline]
475 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
476 where
477 S: Serializer,
478 {
479 #[cfg(feature = "serde-human-readable")]
480 if serializer.is_human_readable() {
481 let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else {
482 return Err(S::Error::custom("failed formatting `UtcDateTime`"));
483 };
484 return serializer.serialize_str(&s);
485 }
486
487 (
488 self.year(),
489 self.ordinal(),
490 self.hour(),
491 self.minute(),
492 self.second(),
493 self.nanosecond(),
494 )
495 .serialize(serializer)
496 }
497}
498
499impl<'a> Deserialize<'a> for UtcDateTime {
500 #[inline]
501 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
502 where
503 D: Deserializer<'a>,
504 {
505 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
506 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
507 } else {
508 deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
509 }
510 }
511}
512
513#[cfg(feature = "parsing")]
515const TIME_FORMAT: FormatDescriptionV3<'_> = FormatDescriptionV3Inner::BorrowedCompound(&[
516 FormatDescriptionV3Inner::Hour24(modifier::Hour24::default()),
517 FormatDescriptionV3Inner::BorrowedLiteral(":"),
518 FormatDescriptionV3Inner::Minute(modifier::Minute::default()),
519 FormatDescriptionV3Inner::BorrowedLiteral(":"),
520 FormatDescriptionV3Inner::Second(modifier::Second::default()),
521 FormatDescriptionV3Inner::BorrowedLiteral("."),
522 FormatDescriptionV3Inner::Subsecond(modifier::Subsecond::default()),
523])
524.into_opaque();
525
526impl Serialize for Time {
527 #[inline]
528 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
529 where
530 S: Serializer,
531 {
532 #[cfg(feature = "serde-human-readable")]
533 if serializer.is_human_readable() {
534 let Ok(s) = self.format(&TIME_FORMAT) else {
535 return Err(S::Error::custom("failed formatting `Time`"));
536 };
537 return serializer.serialize_str(&s);
538 }
539
540 (self.hour(), self.minute(), self.second(), self.nanosecond()).serialize(serializer)
541 }
542}
543
544impl<'a> Deserialize<'a> for Time {
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(4, Visitor::<Self>(PhantomData))
554 }
555 }
556}
557
558#[cfg(feature = "parsing")]
560const UTC_OFFSET_FORMAT: FormatDescriptionV3<'_> = FormatDescriptionV3Inner::BorrowedCompound(&[
561 FormatDescriptionV3Inner::OffsetHour(
562 modifier::OffsetHour::default().with_sign_is_mandatory(true),
563 ),
564 FormatDescriptionV3Inner::BorrowedLiteral(":"),
565 FormatDescriptionV3Inner::OffsetMinute(modifier::OffsetMinute::default()),
566 FormatDescriptionV3Inner::BorrowedLiteral(":"),
567 FormatDescriptionV3Inner::OffsetSecond(modifier::OffsetSecond::default()),
568])
569.into_opaque();
570
571impl Serialize for UtcOffset {
572 #[inline]
573 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
574 where
575 S: Serializer,
576 {
577 #[cfg(feature = "serde-human-readable")]
578 if serializer.is_human_readable() {
579 let Ok(s) = self.format(&UTC_OFFSET_FORMAT) else {
580 return Err(S::Error::custom("failed formatting `UtcOffset`"));
581 };
582 return serializer.serialize_str(&s);
583 }
584
585 (
586 self.whole_hours(),
587 self.minutes_past_hour(),
588 self.seconds_past_minute(),
589 )
590 .serialize(serializer)
591 }
592}
593
594impl<'a> Deserialize<'a> for UtcOffset {
595 #[inline]
596 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
597 where
598 D: Deserializer<'a>,
599 {
600 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
601 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
602 } else {
603 deserializer.deserialize_tuple(3, Visitor::<Self>(PhantomData))
604 }
605 }
606}
607
608impl Serialize for Weekday {
609 #[inline]
610 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
611 where
612 S: Serializer,
613 {
614 #[cfg(feature = "serde-human-readable")]
615 if serializer.is_human_readable() {
616 #[cfg(not(feature = "std"))]
617 use alloc::string::ToString;
618 return self.to_string().serialize(serializer);
619 }
620
621 self.number_from_monday().serialize(serializer)
622 }
623}
624
625impl<'a> Deserialize<'a> for Weekday {
626 #[inline]
627 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
628 where
629 D: Deserializer<'a>,
630 {
631 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
632 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
633 } else {
634 deserializer.deserialize_u8(Visitor::<Self>(PhantomData))
635 }
636 }
637}
638
639impl Serialize for Month {
640 #[inline]
641 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
642 where
643 S: Serializer,
644 {
645 #[cfg(feature = "serde-human-readable")]
646 if serializer.is_human_readable() {
647 #[cfg(not(feature = "std"))]
648 use alloc::string::String;
649 return self.to_string().serialize(serializer);
650 }
651
652 u8::from(*self).serialize(serializer)
653 }
654}
655
656impl<'a> Deserialize<'a> for Month {
657 #[inline]
658 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
659 where
660 D: Deserializer<'a>,
661 {
662 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
663 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
664 } else {
665 deserializer.deserialize_u8(Visitor::<Self>(PhantomData))
666 }
667 }
668}