1macro_rules! item {
10 ($seq:expr, $name:literal) => {
11 $seq.next_element()?
12 .ok_or_else(|| <A::Error as serde::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::ser::Error as _;
31use serde::{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(
69 all(feature = "formatting", feature = "parsing"),
70 doc = "use ::serde::{Serialize, Deserialize};"
71)]
72#[cfg_attr(
73 all(feature = "formatting", not(feature = "parsing")),
74 doc = "use ::serde::Serialize;"
75)]
76#[cfg_attr(
77 all(not(feature = "formatting"), feature = "parsing"),
78 doc = "use ::serde::Deserialize;"
79)]
80#[cfg_attr(
87 all(feature = "formatting", feature = "parsing"),
88 doc = "#[derive(Serialize, Deserialize)]"
89)]
90#[cfg_attr(
91 all(feature = "formatting", not(feature = "parsing")),
92 doc = "#[derive(Serialize)]"
93)]
94#[cfg_attr(
95 all(not(feature = "formatting"), feature = "parsing"),
96 doc = "#[derive(Deserialize)]"
97)]
98#[cfg_attr(
110 all(feature = "formatting", feature = "parsing"),
111 doc = "use ::serde::{Serialize, Deserialize};"
112)]
113#[cfg_attr(
114 all(feature = "formatting", not(feature = "parsing")),
115 doc = "use ::serde::Serialize;"
116)]
117#[cfg_attr(
118 all(not(feature = "formatting"), feature = "parsing"),
119 doc = "use ::serde::Deserialize;"
120)]
121#[cfg_attr(
133 all(feature = "formatting", feature = "parsing"),
134 doc = "#[derive(Serialize, Deserialize)]"
135)]
136#[cfg_attr(
137 all(feature = "formatting", not(feature = "parsing")),
138 doc = "#[derive(Serialize)]"
139)]
140#[cfg_attr(
141 all(not(feature = "formatting"), feature = "parsing"),
142 doc = "#[derive(Deserialize)]"
143)]
144#[cfg_attr(
161 all(feature = "formatting", feature = "parsing"),
162 doc = "use ::serde::{Serialize, Deserialize};"
163)]
164#[cfg_attr(
165 all(feature = "formatting", not(feature = "parsing")),
166 doc = "use ::serde::Serialize;"
167)]
168#[cfg_attr(
169 all(not(feature = "formatting"), feature = "parsing"),
170 doc = "use ::serde::Deserialize;"
171)]
172#[cfg_attr(
187 all(feature = "formatting", feature = "parsing"),
188 doc = "#[derive(Serialize, Deserialize)]"
189)]
190#[cfg_attr(
191 all(feature = "formatting", not(feature = "parsing")),
192 doc = "#[derive(Serialize)]"
193)]
194#[cfg_attr(
195 all(not(feature = "formatting"), feature = "parsing"),
196 doc = "#[derive(Deserialize)]"
197)]
198#[cfg(all(feature = "macros", any(feature = "formatting", feature = "parsing")))]
209pub use time_macros::serde_format_description as format_description;
210
211use self::visitor::Visitor;
212#[cfg(feature = "parsing")]
213use crate::format_description::{modifier, BorrowedFormatItem, Component};
214use crate::{
215 Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcDateTime, UtcOffset, Weekday,
216};
217
218#[cfg(feature = "parsing")]
221const DATE_FORMAT: &[BorrowedFormatItem<'_>] = &[
222 BorrowedFormatItem::Component(Component::Year(modifier::Year::default())),
223 BorrowedFormatItem::Literal(b"-"),
224 BorrowedFormatItem::Component(Component::Month(modifier::Month::default())),
225 BorrowedFormatItem::Literal(b"-"),
226 BorrowedFormatItem::Component(Component::Day(modifier::Day::default())),
227];
228
229impl Serialize for Date {
230 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
231 #[cfg(feature = "serde-human-readable")]
232 if serializer.is_human_readable() {
233 let Ok(s) = self.format(&DATE_FORMAT) else {
234 return Err(S::Error::custom("failed formatting `Date`"));
235 };
236 return serializer.serialize_str(&s);
237 }
238
239 (self.year(), self.ordinal()).serialize(serializer)
240 }
241}
242
243impl<'a> Deserialize<'a> for Date {
244 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
245 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
246 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
247 } else {
248 deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
249 }
250 }
251}
252impl Serialize for Duration {
256 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
257 #[cfg(feature = "serde-human-readable")]
258 if serializer.is_human_readable() {
259 return serializer.collect_str(&format_args!(
260 "{}{}.{:>09}",
261 if self.is_negative() { "-" } else { "" },
262 self.whole_seconds().unsigned_abs(),
263 self.subsec_nanoseconds().abs(),
264 ));
265 }
266
267 (self.whole_seconds(), self.subsec_nanoseconds()).serialize(serializer)
268 }
269}
270
271impl<'a> Deserialize<'a> for Duration {
272 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
273 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
274 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
275 } else {
276 deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
277 }
278 }
279}
280#[cfg(feature = "parsing")]
285const OFFSET_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
286 BorrowedFormatItem::Compound(DATE_FORMAT),
287 BorrowedFormatItem::Literal(b" "),
288 BorrowedFormatItem::Compound(TIME_FORMAT),
289 BorrowedFormatItem::Literal(b" "),
290 BorrowedFormatItem::Compound(UTC_OFFSET_FORMAT),
291];
292
293impl Serialize for OffsetDateTime {
294 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
295 #[cfg(feature = "serde-human-readable")]
296 if serializer.is_human_readable() {
297 let Ok(s) = self.format(&OFFSET_DATE_TIME_FORMAT) else {
298 return Err(S::Error::custom("failed formatting `OffsetDateTime`"));
299 };
300 return serializer.serialize_str(&s);
301 }
302
303 (
304 self.year(),
305 self.ordinal(),
306 self.hour(),
307 self.minute(),
308 self.second(),
309 self.nanosecond(),
310 self.offset().whole_hours(),
311 self.offset().minutes_past_hour(),
312 self.offset().seconds_past_minute(),
313 )
314 .serialize(serializer)
315 }
316}
317
318impl<'a> Deserialize<'a> for OffsetDateTime {
319 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
320 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
321 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
322 } else {
323 deserializer.deserialize_tuple(9, Visitor::<Self>(PhantomData))
324 }
325 }
326}
327#[cfg(feature = "parsing")]
332const PRIMITIVE_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
333 BorrowedFormatItem::Compound(DATE_FORMAT),
334 BorrowedFormatItem::Literal(b" "),
335 BorrowedFormatItem::Compound(TIME_FORMAT),
336];
337
338impl Serialize for PrimitiveDateTime {
339 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
340 #[cfg(feature = "serde-human-readable")]
341 if serializer.is_human_readable() {
342 let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else {
343 return Err(S::Error::custom("failed formatting `PrimitiveDateTime`"));
344 };
345 return serializer.serialize_str(&s);
346 }
347
348 (
349 self.year(),
350 self.ordinal(),
351 self.hour(),
352 self.minute(),
353 self.second(),
354 self.nanosecond(),
355 )
356 .serialize(serializer)
357 }
358}
359
360impl<'a> Deserialize<'a> for PrimitiveDateTime {
361 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
362 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
363 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
364 } else {
365 deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
366 }
367 }
368}
369#[cfg(feature = "parsing")]
374const UTC_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = PRIMITIVE_DATE_TIME_FORMAT;
375
376impl Serialize for UtcDateTime {
377 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
378 #[cfg(feature = "serde-human-readable")]
379 if serializer.is_human_readable() {
380 let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else {
381 return Err(S::Error::custom("failed formatting `UtcDateTime`"));
382 };
383 return serializer.serialize_str(&s);
384 }
385
386 (
387 self.year(),
388 self.ordinal(),
389 self.hour(),
390 self.minute(),
391 self.second(),
392 self.nanosecond(),
393 )
394 .serialize(serializer)
395 }
396}
397
398impl<'a> Deserialize<'a> for UtcDateTime {
399 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
400 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
401 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
402 } else {
403 deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
404 }
405 }
406}
407#[cfg(feature = "parsing")]
412const TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
413 BorrowedFormatItem::Component(Component::Hour(modifier::Hour::default())),
414 BorrowedFormatItem::Literal(b":"),
415 BorrowedFormatItem::Component(Component::Minute(modifier::Minute::default())),
416 BorrowedFormatItem::Literal(b":"),
417 BorrowedFormatItem::Component(Component::Second(modifier::Second::default())),
418 BorrowedFormatItem::Literal(b"."),
419 BorrowedFormatItem::Component(Component::Subsecond(modifier::Subsecond::default())),
420];
421
422impl Serialize for Time {
423 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
424 #[cfg(feature = "serde-human-readable")]
425 if serializer.is_human_readable() {
426 let Ok(s) = self.format(&TIME_FORMAT) else {
427 return Err(S::Error::custom("failed formatting `Time`"));
428 };
429 return serializer.serialize_str(&s);
430 }
431
432 (self.hour(), self.minute(), self.second(), self.nanosecond()).serialize(serializer)
433 }
434}
435
436impl<'a> Deserialize<'a> for Time {
437 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
438 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
439 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
440 } else {
441 deserializer.deserialize_tuple(4, Visitor::<Self>(PhantomData))
442 }
443 }
444}
445#[cfg(feature = "parsing")]
450const UTC_OFFSET_HOUR: modifier::OffsetHour = {
451 let mut m = modifier::OffsetHour::default();
452 m.sign_is_mandatory = true;
453 m
454};
455#[cfg(feature = "parsing")]
456const UTC_OFFSET_MINUTE: modifier::OffsetMinute = modifier::OffsetMinute::default();
457#[cfg(feature = "parsing")]
458const UTC_OFFSET_SECOND: modifier::OffsetSecond = modifier::OffsetSecond::default();
459#[cfg(feature = "parsing")]
461const UTC_OFFSET_FORMAT: &[BorrowedFormatItem<'_>] = &[
462 BorrowedFormatItem::Component(Component::OffsetHour(UTC_OFFSET_HOUR)),
463 BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
464 BorrowedFormatItem::Literal(b":"),
465 BorrowedFormatItem::Component(Component::OffsetMinute(UTC_OFFSET_MINUTE)),
466 BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
467 BorrowedFormatItem::Literal(b":"),
468 BorrowedFormatItem::Component(Component::OffsetSecond(UTC_OFFSET_SECOND)),
469 ])),
470 ])),
471];
472
473impl Serialize for UtcOffset {
474 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
475 #[cfg(feature = "serde-human-readable")]
476 if serializer.is_human_readable() {
477 let Ok(s) = self.format(&UTC_OFFSET_FORMAT) else {
478 return Err(S::Error::custom("failed formatting `UtcOffset`"));
479 };
480 return serializer.serialize_str(&s);
481 }
482
483 (
484 self.whole_hours(),
485 self.minutes_past_hour(),
486 self.seconds_past_minute(),
487 )
488 .serialize(serializer)
489 }
490}
491
492impl<'a> Deserialize<'a> for UtcOffset {
493 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
494 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
495 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
496 } else {
497 deserializer.deserialize_tuple(3, Visitor::<Self>(PhantomData))
498 }
499 }
500}
501impl Serialize for Weekday {
505 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
506 #[cfg(feature = "serde-human-readable")]
507 if serializer.is_human_readable() {
508 #[cfg(not(feature = "std"))]
509 use alloc::string::ToString;
510 return self.to_string().serialize(serializer);
511 }
512
513 self.number_from_monday().serialize(serializer)
514 }
515}
516
517impl<'a> Deserialize<'a> for Weekday {
518 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
519 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
520 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
521 } else {
522 deserializer.deserialize_u8(Visitor::<Self>(PhantomData))
523 }
524 }
525}
526impl Serialize for Month {
530 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
531 #[cfg(feature = "serde-human-readable")]
532 if serializer.is_human_readable() {
533 #[cfg(not(feature = "std"))]
534 use alloc::string::String;
535 return self.to_string().serialize(serializer);
536 }
537
538 u8::from(*self).serialize(serializer)
539 }
540}
541
542impl<'a> Deserialize<'a> for Month {
543 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
544 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
545 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
546 } else {
547 deserializer.deserialize_u8(Visitor::<Self>(PhantomData))
548 }
549 }
550}
551