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(
185 all(feature = "formatting", feature = "parsing"),
186 doc = "#[derive(Serialize, Deserialize)]"
187)]
188#[cfg_attr(
189 all(feature = "formatting", not(feature = "parsing")),
190 doc = "#[derive(Serialize)]"
191)]
192#[cfg_attr(
193 all(not(feature = "formatting"), feature = "parsing"),
194 doc = "#[derive(Deserialize)]"
195)]
196#[cfg(all(feature = "macros", any(feature = "formatting", feature = "parsing"),))]
207pub use time_macros::serde_format_description as format_description;
208
209use self::visitor::Visitor;
210#[cfg(feature = "parsing")]
211use crate::format_description::{modifier, BorrowedFormatItem, Component};
212use crate::{Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcOffset, Weekday};
213
214#[cfg(feature = "parsing")]
217const DATE_FORMAT: &[BorrowedFormatItem<'_>] = &[
218 BorrowedFormatItem::Component(Component::Year(modifier::Year::default())),
219 BorrowedFormatItem::Literal(b"-"),
220 BorrowedFormatItem::Component(Component::Month(modifier::Month::default())),
221 BorrowedFormatItem::Literal(b"-"),
222 BorrowedFormatItem::Component(Component::Day(modifier::Day::default())),
223];
224
225impl Serialize for Date {
226 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
227 #[cfg(feature = "serde-human-readable")]
228 if serializer.is_human_readable() {
229 let Ok(s) = self.format(&DATE_FORMAT) else {
230 return Err(S::Error::custom("failed formatting `Date`"));
231 };
232 return serializer.serialize_str(&s);
233 }
234
235 (self.year(), self.ordinal()).serialize(serializer)
236 }
237}
238
239impl<'a> Deserialize<'a> for Date {
240 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
241 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
242 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
243 } else {
244 deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
245 }
246 }
247}
248impl Serialize for Duration {
252 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
253 #[cfg(feature = "serde-human-readable")]
254 if serializer.is_human_readable() {
255 return serializer.collect_str(&format_args!(
256 "{}.{:>09}",
257 self.whole_seconds(),
258 self.subsec_nanoseconds().abs()
259 ));
260 }
261
262 (self.whole_seconds(), self.subsec_nanoseconds()).serialize(serializer)
263 }
264}
265
266impl<'a> Deserialize<'a> for Duration {
267 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
268 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
269 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
270 } else {
271 deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
272 }
273 }
274}
275#[cfg(feature = "parsing")]
280const OFFSET_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
281 BorrowedFormatItem::Compound(DATE_FORMAT),
282 BorrowedFormatItem::Literal(b" "),
283 BorrowedFormatItem::Compound(TIME_FORMAT),
284 BorrowedFormatItem::Literal(b" "),
285 BorrowedFormatItem::Compound(UTC_OFFSET_FORMAT),
286];
287
288impl Serialize for OffsetDateTime {
289 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
290 #[cfg(feature = "serde-human-readable")]
291 if serializer.is_human_readable() {
292 let Ok(s) = self.format(&OFFSET_DATE_TIME_FORMAT) else {
293 return Err(S::Error::custom("failed formatting `OffsetDateTime`"));
294 };
295 return serializer.serialize_str(&s);
296 }
297
298 (
299 self.year(),
300 self.ordinal(),
301 self.hour(),
302 self.minute(),
303 self.second(),
304 self.nanosecond(),
305 self.offset().whole_hours(),
306 self.offset().minutes_past_hour(),
307 self.offset().seconds_past_minute(),
308 )
309 .serialize(serializer)
310 }
311}
312
313impl<'a> Deserialize<'a> for OffsetDateTime {
314 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
315 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
316 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
317 } else {
318 deserializer.deserialize_tuple(9, Visitor::<Self>(PhantomData))
319 }
320 }
321}
322#[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#[cfg(feature = "parsing")]
369const TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
370 BorrowedFormatItem::Component(Component::Hour(modifier::Hour::default())),
371 BorrowedFormatItem::Literal(b":"),
372 BorrowedFormatItem::Component(Component::Minute(modifier::Minute::default())),
373 BorrowedFormatItem::Literal(b":"),
374 BorrowedFormatItem::Component(Component::Second(modifier::Second::default())),
375 BorrowedFormatItem::Literal(b"."),
376 BorrowedFormatItem::Component(Component::Subsecond(modifier::Subsecond::default())),
377];
378
379impl Serialize for Time {
380 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
381 #[cfg(feature = "serde-human-readable")]
382 if serializer.is_human_readable() {
383 let Ok(s) = self.format(&TIME_FORMAT) else {
384 return Err(S::Error::custom("failed formatting `Time`"));
385 };
386 return serializer.serialize_str(&s);
387 }
388
389 (self.hour(), self.minute(), self.second(), self.nanosecond()).serialize(serializer)
390 }
391}
392
393impl<'a> Deserialize<'a> for Time {
394 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
395 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
396 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
397 } else {
398 deserializer.deserialize_tuple(4, Visitor::<Self>(PhantomData))
399 }
400 }
401}
402#[cfg(feature = "parsing")]
407const UTC_OFFSET_FORMAT: &[BorrowedFormatItem<'_>] = &[
408 BorrowedFormatItem::Component(Component::OffsetHour({
409 let mut m = modifier::OffsetHour::default();
410 m.sign_is_mandatory = true;
411 m
412 })),
413 BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
414 BorrowedFormatItem::Literal(b":"),
415 BorrowedFormatItem::Component(Component::OffsetMinute(modifier::OffsetMinute::default())),
416 BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
417 BorrowedFormatItem::Literal(b":"),
418 BorrowedFormatItem::Component(Component::OffsetSecond(
419 modifier::OffsetSecond::default(),
420 )),
421 ])),
422 ])),
423];
424
425impl Serialize for UtcOffset {
426 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
427 #[cfg(feature = "serde-human-readable")]
428 if serializer.is_human_readable() {
429 let Ok(s) = self.format(&UTC_OFFSET_FORMAT) else {
430 return Err(S::Error::custom("failed formatting `UtcOffset`"));
431 };
432 return serializer.serialize_str(&s);
433 }
434
435 (
436 self.whole_hours(),
437 self.minutes_past_hour(),
438 self.seconds_past_minute(),
439 )
440 .serialize(serializer)
441 }
442}
443
444impl<'a> Deserialize<'a> for UtcOffset {
445 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
446 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
447 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
448 } else {
449 deserializer.deserialize_tuple(3, Visitor::<Self>(PhantomData))
450 }
451 }
452}
453impl Serialize for Weekday {
457 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
458 #[cfg(feature = "serde-human-readable")]
459 if serializer.is_human_readable() {
460 #[cfg(not(feature = "std"))]
461 use alloc::string::ToString;
462 return self.to_string().serialize(serializer);
463 }
464
465 self.number_from_monday().serialize(serializer)
466 }
467}
468
469impl<'a> Deserialize<'a> for Weekday {
470 fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
471 if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
472 deserializer.deserialize_any(Visitor::<Self>(PhantomData))
473 } else {
474 deserializer.deserialize_u8(Visitor::<Self>(PhantomData))
475 }
476 }
477}
478impl Serialize for Month {
482 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
483 #[cfg(feature = "serde-human-readable")]
484 if serializer.is_human_readable() {
485 #[cfg(not(feature = "std"))]
486 use alloc::string::String;
487 return self.to_string().serialize(serializer);
488 }
489
490 u8::from(*self).serialize(serializer)
491 }
492}
493
494impl<'a> Deserialize<'a> for Month {
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_u8(Visitor::<Self>(PhantomData))
500 }
501 }
502}
503