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")]
223const DATE_FORMAT: &[BorrowedFormatItem<'_>] = &[
224 BorrowedFormatItem::Component(Component::Year(modifier::Year::default())),
225 BorrowedFormatItem::Literal(b"-"),
226 BorrowedFormatItem::Component(Component::Month(modifier::Month::default())),
227 BorrowedFormatItem::Literal(b"-"),
228 BorrowedFormatItem::Component(Component::Day(modifier::Day::default())),
229];
230
231impl Serialize for Date {
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 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
247 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
248 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
249 } else {
250 deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
251 }
252 }
253}
254impl Serialize for Duration {
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 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
275 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
276 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
277 } else {
278 deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
279 }
280 }
281}
282#[cfg(feature = "parsing")]
287const OFFSET_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
288 BorrowedFormatItem::Compound(DATE_FORMAT),
289 BorrowedFormatItem::Literal(b" "),
290 BorrowedFormatItem::Compound(TIME_FORMAT),
291 BorrowedFormatItem::Literal(b" "),
292 BorrowedFormatItem::Compound(UTC_OFFSET_FORMAT),
293];
294
295impl Serialize for OffsetDateTime {
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 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
322 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
323 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
324 } else {
325 deserializer.deserialize_tuple(9, Visitor::<Self>(PhantomData))
326 }
327 }
328}
329#[cfg(feature = "parsing")]
334const PRIMITIVE_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
335 BorrowedFormatItem::Compound(DATE_FORMAT),
336 BorrowedFormatItem::Literal(b" "),
337 BorrowedFormatItem::Compound(TIME_FORMAT),
338];
339
340impl Serialize for PrimitiveDateTime {
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 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
364 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
365 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
366 } else {
367 deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
368 }
369 }
370}
371#[cfg(feature = "parsing")]
376const UTC_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = PRIMITIVE_DATE_TIME_FORMAT;
377
378impl Serialize for UtcDateTime {
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 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
402 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
403 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
404 } else {
405 deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
406 }
407 }
408}
409#[cfg(feature = "parsing")]
414const TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
415 BorrowedFormatItem::Component(Component::Hour(modifier::Hour::default())),
416 BorrowedFormatItem::Literal(b":"),
417 BorrowedFormatItem::Component(Component::Minute(modifier::Minute::default())),
418 BorrowedFormatItem::Literal(b":"),
419 BorrowedFormatItem::Component(Component::Second(modifier::Second::default())),
420 BorrowedFormatItem::Literal(b"."),
421 BorrowedFormatItem::Component(Component::Subsecond(modifier::Subsecond::default())),
422];
423
424impl Serialize for Time {
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 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
440 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
441 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
442 } else {
443 deserializer.deserialize_tuple(4, Visitor::<Self>(PhantomData))
444 }
445 }
446}
447#[cfg(feature = "parsing")]
452const UTC_OFFSET_HOUR: modifier::OffsetHour = {
453 let mut m = modifier::OffsetHour::default();
454 m.sign_is_mandatory = true;
455 m
456};
457#[cfg(feature = "parsing")]
458const UTC_OFFSET_MINUTE: modifier::OffsetMinute = modifier::OffsetMinute::default();
459#[cfg(feature = "parsing")]
460const UTC_OFFSET_SECOND: modifier::OffsetSecond = modifier::OffsetSecond::default();
461#[cfg(feature = "parsing")]
463const UTC_OFFSET_FORMAT: &[BorrowedFormatItem<'_>] = &[
464 BorrowedFormatItem::Component(Component::OffsetHour(UTC_OFFSET_HOUR)),
465 BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
466 BorrowedFormatItem::Literal(b":"),
467 BorrowedFormatItem::Component(Component::OffsetMinute(UTC_OFFSET_MINUTE)),
468 BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
469 BorrowedFormatItem::Literal(b":"),
470 BorrowedFormatItem::Component(Component::OffsetSecond(UTC_OFFSET_SECOND)),
471 ])),
472 ])),
473];
474
475impl Serialize for UtcOffset {
476 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
477 #[cfg(feature = "serde-human-readable")]
478 if serializer.is_human_readable() {
479 let Ok(s) = self.format(&UTC_OFFSET_FORMAT) else {
480 return Err(S::Error::custom("failed formatting `UtcOffset`"));
481 };
482 return serializer.serialize_str(&s);
483 }
484
485 (
486 self.whole_hours(),
487 self.minutes_past_hour(),
488 self.seconds_past_minute(),
489 )
490 .serialize(serializer)
491 }
492}
493
494impl<'a> Deserialize<'a> for UtcOffset {
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}
503impl Serialize for Weekday {
507 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
508 #[cfg(feature = "serde-human-readable")]
509 if serializer.is_human_readable() {
510 #[cfg(not(feature = "std"))]
511 use alloc::string::ToString;
512 return self.to_string().serialize(serializer);
513 }
514
515 self.number_from_monday().serialize(serializer)
516 }
517}
518
519impl<'a> Deserialize<'a> for Weekday {
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}
528impl Serialize for Month {
532 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
533 #[cfg(feature = "serde-human-readable")]
534 if serializer.is_human_readable() {
535 #[cfg(not(feature = "std"))]
536 use alloc::string::String;
537 return self.to_string().serialize(serializer);
538 }
539
540 u8::from(*self).serialize(serializer)
541 }
542}
543
544impl<'a> Deserialize<'a> for Month {
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}
553