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