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