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 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
232 #[cfg(feature = "serde-human-readable")]
233 if serializer.is_human_readable() {
234 let Ok(s) = self.format(&DATE_FORMAT) else {
235 return Err(S::Error::custom("failed formatting `Date`"));
236 };
237 return serializer.serialize_str(&s);
238 }
239
240 (self.year(), self.ordinal()).serialize(serializer)
241 }
242}
243
244impl<'a> Deserialize<'a> for Date {
245 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
246 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
247 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
248 } else {
249 deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
250 }
251 }
252}
253
254impl Serialize for Duration {
255 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
256 #[cfg(feature = "serde-human-readable")]
257 if serializer.is_human_readable() {
258 return serializer.collect_str(&format_args!(
259 "{}{}.{:>09}",
260 if self.is_negative() { "-" } else { "" },
261 self.whole_seconds().unsigned_abs(),
262 self.subsec_nanoseconds().abs(),
263 ));
264 }
265
266 (self.whole_seconds(), self.subsec_nanoseconds()).serialize(serializer)
267 }
268}
269
270impl<'a> Deserialize<'a> for Duration {
271 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
272 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
273 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
274 } else {
275 deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
276 }
277 }
278}
279
280#[cfg(feature = "parsing")]
282const OFFSET_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
283 BorrowedFormatItem::Compound(DATE_FORMAT),
284 BorrowedFormatItem::Literal(b" "),
285 BorrowedFormatItem::Compound(TIME_FORMAT),
286 BorrowedFormatItem::Literal(b" "),
287 BorrowedFormatItem::Compound(UTC_OFFSET_FORMAT),
288];
289
290impl Serialize for OffsetDateTime {
291 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
292 #[cfg(feature = "serde-human-readable")]
293 if serializer.is_human_readable() {
294 let Ok(s) = self.format(&OFFSET_DATE_TIME_FORMAT) else {
295 return Err(S::Error::custom("failed formatting `OffsetDateTime`"));
296 };
297 return serializer.serialize_str(&s);
298 }
299
300 (
301 self.year(),
302 self.ordinal(),
303 self.hour(),
304 self.minute(),
305 self.second(),
306 self.nanosecond(),
307 self.offset().whole_hours(),
308 self.offset().minutes_past_hour(),
309 self.offset().seconds_past_minute(),
310 )
311 .serialize(serializer)
312 }
313}
314
315impl<'a> Deserialize<'a> for OffsetDateTime {
316 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
317 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
318 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
319 } else {
320 deserializer.deserialize_tuple(9, Visitor::<Self>(PhantomData))
321 }
322 }
323}
324
325#[cfg(feature = "parsing")]
327const PRIMITIVE_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
328 BorrowedFormatItem::Compound(DATE_FORMAT),
329 BorrowedFormatItem::Literal(b" "),
330 BorrowedFormatItem::Compound(TIME_FORMAT),
331];
332
333impl Serialize for PrimitiveDateTime {
334 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
335 #[cfg(feature = "serde-human-readable")]
336 if serializer.is_human_readable() {
337 let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else {
338 return Err(S::Error::custom("failed formatting `PrimitiveDateTime`"));
339 };
340 return serializer.serialize_str(&s);
341 }
342
343 (
344 self.year(),
345 self.ordinal(),
346 self.hour(),
347 self.minute(),
348 self.second(),
349 self.nanosecond(),
350 )
351 .serialize(serializer)
352 }
353}
354
355impl<'a> Deserialize<'a> for PrimitiveDateTime {
356 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
357 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
358 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
359 } else {
360 deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
361 }
362 }
363}
364
365#[cfg(feature = "parsing")]
367const UTC_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = PRIMITIVE_DATE_TIME_FORMAT;
368
369impl Serialize for UtcDateTime {
370 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
371 #[cfg(feature = "serde-human-readable")]
372 if serializer.is_human_readable() {
373 let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else {
374 return Err(S::Error::custom("failed formatting `UtcDateTime`"));
375 };
376 return serializer.serialize_str(&s);
377 }
378
379 (
380 self.year(),
381 self.ordinal(),
382 self.hour(),
383 self.minute(),
384 self.second(),
385 self.nanosecond(),
386 )
387 .serialize(serializer)
388 }
389}
390
391impl<'a> Deserialize<'a> for UtcDateTime {
392 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
393 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
394 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
395 } else {
396 deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
397 }
398 }
399}
400
401#[cfg(feature = "parsing")]
403const TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
404 BorrowedFormatItem::Component(Component::Hour(modifier::Hour::default())),
405 BorrowedFormatItem::Literal(b":"),
406 BorrowedFormatItem::Component(Component::Minute(modifier::Minute::default())),
407 BorrowedFormatItem::Literal(b":"),
408 BorrowedFormatItem::Component(Component::Second(modifier::Second::default())),
409 BorrowedFormatItem::Literal(b"."),
410 BorrowedFormatItem::Component(Component::Subsecond(modifier::Subsecond::default())),
411];
412
413impl Serialize for Time {
414 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
415 #[cfg(feature = "serde-human-readable")]
416 if serializer.is_human_readable() {
417 let Ok(s) = self.format(&TIME_FORMAT) else {
418 return Err(S::Error::custom("failed formatting `Time`"));
419 };
420 return serializer.serialize_str(&s);
421 }
422
423 (self.hour(), self.minute(), self.second(), self.nanosecond()).serialize(serializer)
424 }
425}
426
427impl<'a> Deserialize<'a> for Time {
428 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
429 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
430 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
431 } else {
432 deserializer.deserialize_tuple(4, Visitor::<Self>(PhantomData))
433 }
434 }
435}
436
437#[cfg(feature = "parsing")]
439const UTC_OFFSET_HOUR: modifier::OffsetHour = {
440 let mut m = modifier::OffsetHour::default();
441 m.sign_is_mandatory = true;
442 m
443};
444#[cfg(feature = "parsing")]
445const UTC_OFFSET_MINUTE: modifier::OffsetMinute = modifier::OffsetMinute::default();
446#[cfg(feature = "parsing")]
447const UTC_OFFSET_SECOND: modifier::OffsetSecond = modifier::OffsetSecond::default();
448#[cfg(feature = "parsing")]
450const UTC_OFFSET_FORMAT: &[BorrowedFormatItem<'_>] = &[
451 BorrowedFormatItem::Component(Component::OffsetHour(UTC_OFFSET_HOUR)),
452 BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
453 BorrowedFormatItem::Literal(b":"),
454 BorrowedFormatItem::Component(Component::OffsetMinute(UTC_OFFSET_MINUTE)),
455 BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
456 BorrowedFormatItem::Literal(b":"),
457 BorrowedFormatItem::Component(Component::OffsetSecond(UTC_OFFSET_SECOND)),
458 ])),
459 ])),
460];
461
462impl Serialize for UtcOffset {
463 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
464 #[cfg(feature = "serde-human-readable")]
465 if serializer.is_human_readable() {
466 let Ok(s) = self.format(&UTC_OFFSET_FORMAT) else {
467 return Err(S::Error::custom("failed formatting `UtcOffset`"));
468 };
469 return serializer.serialize_str(&s);
470 }
471
472 (
473 self.whole_hours(),
474 self.minutes_past_hour(),
475 self.seconds_past_minute(),
476 )
477 .serialize(serializer)
478 }
479}
480
481impl<'a> Deserialize<'a> for UtcOffset {
482 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
483 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
484 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
485 } else {
486 deserializer.deserialize_tuple(3, Visitor::<Self>(PhantomData))
487 }
488 }
489}
490
491impl Serialize for Weekday {
492 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
493 #[cfg(feature = "serde-human-readable")]
494 if serializer.is_human_readable() {
495 #[cfg(not(feature = "std"))]
496 use alloc::string::ToString;
497 return self.to_string().serialize(serializer);
498 }
499
500 self.number_from_monday().serialize(serializer)
501 }
502}
503
504impl<'a> Deserialize<'a> for Weekday {
505 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
506 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
507 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
508 } else {
509 deserializer.deserialize_u8(Visitor::<Self>(PhantomData))
510 }
511 }
512}
513
514impl Serialize for Month {
515 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
516 #[cfg(feature = "serde-human-readable")]
517 if serializer.is_human_readable() {
518 #[cfg(not(feature = "std"))]
519 use alloc::string::String;
520 return self.to_string().serialize(serializer);
521 }
522
523 u8::from(*self).serialize(serializer)
524 }
525}
526
527impl<'a> Deserialize<'a> for Month {
528 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
529 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
530 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
531 } else {
532 deserializer.deserialize_u8(Visitor::<Self>(PhantomData))
533 }
534 }
535}