macro_rules! item {
($seq:expr, $name:literal) => {
$seq.next_element()?
.ok_or_else(|| <A::Error as serde::de::Error>::custom(concat!("expected ", $name)))
};
}
#[cfg(any(feature = "formatting", feature = "parsing"))]
pub mod iso8601;
#[cfg(any(feature = "formatting", feature = "parsing"))]
pub mod rfc2822;
#[cfg(any(feature = "formatting", feature = "parsing"))]
pub mod rfc3339;
pub mod timestamp;
mod visitor;
#[cfg(feature = "serde-human-readable")]
use alloc::string::ToString;
use core::marker::PhantomData;
#[cfg(feature = "serde-human-readable")]
use serde::ser::Error as _;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[cfg_attr(
all(feature = "formatting", feature = "parsing"),
doc = "[`Formattable`](crate::formatting::Formattable) and \
[`Parsable`](crate::parsing::Parsable)."
)]
#[cfg_attr(
all(feature = "formatting", not(feature = "parsing")),
doc = "[`Formattable`](crate::formatting::Formattable)."
)]
#[cfg_attr(
all(not(feature = "formatting"), feature = "parsing"),
doc = "[`Parsable`](crate::parsing::Parsable)."
)]
#[cfg_attr(
all(feature = "formatting", feature = "parsing"),
doc = "use ::serde::{Serialize, Deserialize};"
)]
#[cfg_attr(
all(feature = "formatting", not(feature = "parsing")),
doc = "use ::serde::Serialize;"
)]
#[cfg_attr(
all(not(feature = "formatting"), feature = "parsing"),
doc = "use ::serde::Deserialize;"
)]
#[cfg_attr(
all(feature = "formatting", feature = "parsing"),
doc = "#[derive(Serialize, Deserialize)]"
)]
#[cfg_attr(
all(feature = "formatting", not(feature = "parsing")),
doc = "#[derive(Serialize)]"
)]
#[cfg_attr(
all(not(feature = "formatting"), feature = "parsing"),
doc = "#[derive(Deserialize)]"
)]
#[cfg_attr(
all(feature = "formatting", feature = "parsing"),
doc = "use ::serde::{Serialize, Deserialize};"
)]
#[cfg_attr(
all(feature = "formatting", not(feature = "parsing")),
doc = "use ::serde::Serialize;"
)]
#[cfg_attr(
all(not(feature = "formatting"), feature = "parsing"),
doc = "use ::serde::Deserialize;"
)]
#[cfg_attr(
all(feature = "formatting", feature = "parsing"),
doc = "#[derive(Serialize, Deserialize)]"
)]
#[cfg_attr(
all(feature = "formatting", not(feature = "parsing")),
doc = "#[derive(Serialize)]"
)]
#[cfg_attr(
all(not(feature = "formatting"), feature = "parsing"),
doc = "#[derive(Deserialize)]"
)]
#[cfg_attr(
all(feature = "formatting", feature = "parsing"),
doc = "use ::serde::{Serialize, Deserialize};"
)]
#[cfg_attr(
all(feature = "formatting", not(feature = "parsing")),
doc = "use ::serde::Serialize;"
)]
#[cfg_attr(
all(not(feature = "formatting"), feature = "parsing"),
doc = "use ::serde::Deserialize;"
)]
#[cfg_attr(
all(feature = "formatting", feature = "parsing"),
doc = "#[derive(Serialize, Deserialize)]"
)]
#[cfg_attr(
all(feature = "formatting", not(feature = "parsing")),
doc = "#[derive(Serialize)]"
)]
#[cfg_attr(
all(not(feature = "formatting"), feature = "parsing"),
doc = "#[derive(Deserialize)]"
)]
#[cfg(all(feature = "macros", any(feature = "formatting", feature = "parsing")))]
pub use time_macros::serde_format_description as format_description;
use self::visitor::Visitor;
#[cfg(feature = "parsing")]
use crate::format_description::{modifier, BorrowedFormatItem, Component};
use crate::{
Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcDateTime, UtcOffset, Weekday,
};
#[cfg(feature = "parsing")]
const DATE_FORMAT: &[BorrowedFormatItem<'_>] = &[
BorrowedFormatItem::Component(Component::Year(modifier::Year::default())),
BorrowedFormatItem::Literal(b"-"),
BorrowedFormatItem::Component(Component::Month(modifier::Month::default())),
BorrowedFormatItem::Literal(b"-"),
BorrowedFormatItem::Component(Component::Day(modifier::Day::default())),
];
impl Serialize for Date {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
#[cfg(feature = "serde-human-readable")]
if serializer.is_human_readable() {
let Ok(s) = self.format(&DATE_FORMAT) else {
return Err(S::Error::custom("failed formatting `Date`"));
};
return serializer.serialize_str(&s);
}
(self.year(), self.ordinal()).serialize(serializer)
}
}
impl<'a> Deserialize<'a> for Date {
fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
deserializer.deserialize_any(Visitor::<Self>(PhantomData))
} else {
deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
}
}
}
impl Serialize for Duration {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
#[cfg(feature = "serde-human-readable")]
if serializer.is_human_readable() {
return serializer.collect_str(&format_args!(
"{}{}.{:>09}",
if self.is_negative() { "-" } else { "" },
self.whole_seconds().unsigned_abs(),
self.subsec_nanoseconds().abs(),
));
}
(self.whole_seconds(), self.subsec_nanoseconds()).serialize(serializer)
}
}
impl<'a> Deserialize<'a> for Duration {
fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
deserializer.deserialize_any(Visitor::<Self>(PhantomData))
} else {
deserializer.deserialize_tuple(2, Visitor::<Self>(PhantomData))
}
}
}
#[cfg(feature = "parsing")]
const OFFSET_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
BorrowedFormatItem::Compound(DATE_FORMAT),
BorrowedFormatItem::Literal(b" "),
BorrowedFormatItem::Compound(TIME_FORMAT),
BorrowedFormatItem::Literal(b" "),
BorrowedFormatItem::Compound(UTC_OFFSET_FORMAT),
];
impl Serialize for OffsetDateTime {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
#[cfg(feature = "serde-human-readable")]
if serializer.is_human_readable() {
let Ok(s) = self.format(&OFFSET_DATE_TIME_FORMAT) else {
return Err(S::Error::custom("failed formatting `OffsetDateTime`"));
};
return serializer.serialize_str(&s);
}
(
self.year(),
self.ordinal(),
self.hour(),
self.minute(),
self.second(),
self.nanosecond(),
self.offset().whole_hours(),
self.offset().minutes_past_hour(),
self.offset().seconds_past_minute(),
)
.serialize(serializer)
}
}
impl<'a> Deserialize<'a> for OffsetDateTime {
fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
deserializer.deserialize_any(Visitor::<Self>(PhantomData))
} else {
deserializer.deserialize_tuple(9, Visitor::<Self>(PhantomData))
}
}
}
#[cfg(feature = "parsing")]
const PRIMITIVE_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
BorrowedFormatItem::Compound(DATE_FORMAT),
BorrowedFormatItem::Literal(b" "),
BorrowedFormatItem::Compound(TIME_FORMAT),
];
impl Serialize for PrimitiveDateTime {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
#[cfg(feature = "serde-human-readable")]
if serializer.is_human_readable() {
let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else {
return Err(S::Error::custom("failed formatting `PrimitiveDateTime`"));
};
return serializer.serialize_str(&s);
}
(
self.year(),
self.ordinal(),
self.hour(),
self.minute(),
self.second(),
self.nanosecond(),
)
.serialize(serializer)
}
}
impl<'a> Deserialize<'a> for PrimitiveDateTime {
fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
deserializer.deserialize_any(Visitor::<Self>(PhantomData))
} else {
deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
}
}
}
#[cfg(feature = "parsing")]
const UTC_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = PRIMITIVE_DATE_TIME_FORMAT;
impl Serialize for UtcDateTime {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
#[cfg(feature = "serde-human-readable")]
if serializer.is_human_readable() {
let Ok(s) = self.format(&PRIMITIVE_DATE_TIME_FORMAT) else {
return Err(S::Error::custom("failed formatting `UtcDateTime`"));
};
return serializer.serialize_str(&s);
}
(
self.year(),
self.ordinal(),
self.hour(),
self.minute(),
self.second(),
self.nanosecond(),
)
.serialize(serializer)
}
}
impl<'a> Deserialize<'a> for UtcDateTime {
fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
deserializer.deserialize_any(Visitor::<Self>(PhantomData))
} else {
deserializer.deserialize_tuple(6, Visitor::<Self>(PhantomData))
}
}
}
#[cfg(feature = "parsing")]
const TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
BorrowedFormatItem::Component(Component::Hour(modifier::Hour::default())),
BorrowedFormatItem::Literal(b":"),
BorrowedFormatItem::Component(Component::Minute(modifier::Minute::default())),
BorrowedFormatItem::Literal(b":"),
BorrowedFormatItem::Component(Component::Second(modifier::Second::default())),
BorrowedFormatItem::Literal(b"."),
BorrowedFormatItem::Component(Component::Subsecond(modifier::Subsecond::default())),
];
impl Serialize for Time {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
#[cfg(feature = "serde-human-readable")]
if serializer.is_human_readable() {
let Ok(s) = self.format(&TIME_FORMAT) else {
return Err(S::Error::custom("failed formatting `Time`"));
};
return serializer.serialize_str(&s);
}
(self.hour(), self.minute(), self.second(), self.nanosecond()).serialize(serializer)
}
}
impl<'a> Deserialize<'a> for Time {
fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
deserializer.deserialize_any(Visitor::<Self>(PhantomData))
} else {
deserializer.deserialize_tuple(4, Visitor::<Self>(PhantomData))
}
}
}
#[cfg(feature = "parsing")]
const UTC_OFFSET_HOUR: modifier::OffsetHour = {
let mut m = modifier::OffsetHour::default();
m.sign_is_mandatory = true;
m
};
#[cfg(feature = "parsing")]
const UTC_OFFSET_MINUTE: modifier::OffsetMinute = modifier::OffsetMinute::default();
#[cfg(feature = "parsing")]
const UTC_OFFSET_SECOND: modifier::OffsetSecond = modifier::OffsetSecond::default();
#[cfg(feature = "parsing")]
const UTC_OFFSET_FORMAT: &[BorrowedFormatItem<'_>] = &[
BorrowedFormatItem::Component(Component::OffsetHour(UTC_OFFSET_HOUR)),
BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
BorrowedFormatItem::Literal(b":"),
BorrowedFormatItem::Component(Component::OffsetMinute(UTC_OFFSET_MINUTE)),
BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
BorrowedFormatItem::Literal(b":"),
BorrowedFormatItem::Component(Component::OffsetSecond(UTC_OFFSET_SECOND)),
])),
])),
];
impl Serialize for UtcOffset {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
#[cfg(feature = "serde-human-readable")]
if serializer.is_human_readable() {
let Ok(s) = self.format(&UTC_OFFSET_FORMAT) else {
return Err(S::Error::custom("failed formatting `UtcOffset`"));
};
return serializer.serialize_str(&s);
}
(
self.whole_hours(),
self.minutes_past_hour(),
self.seconds_past_minute(),
)
.serialize(serializer)
}
}
impl<'a> Deserialize<'a> for UtcOffset {
fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
deserializer.deserialize_any(Visitor::<Self>(PhantomData))
} else {
deserializer.deserialize_tuple(3, Visitor::<Self>(PhantomData))
}
}
}
impl Serialize for Weekday {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
#[cfg(feature = "serde-human-readable")]
if serializer.is_human_readable() {
#[cfg(not(feature = "std"))]
use alloc::string::ToString;
return self.to_string().serialize(serializer);
}
self.number_from_monday().serialize(serializer)
}
}
impl<'a> Deserialize<'a> for Weekday {
fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
deserializer.deserialize_any(Visitor::<Self>(PhantomData))
} else {
deserializer.deserialize_u8(Visitor::<Self>(PhantomData))
}
}
}
impl Serialize for Month {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
#[cfg(feature = "serde-human-readable")]
if serializer.is_human_readable() {
#[cfg(not(feature = "std"))]
use alloc::string::String;
return self.to_string().serialize(serializer);
}
u8::from(*self).serialize(serializer)
}
}
impl<'a> Deserialize<'a> for Month {
fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
if cfg!(feature = "serde-human-readable") && deserializer.is_human_readable() {
deserializer.deserialize_any(Visitor::<Self>(PhantomData))
} else {
deserializer.deserialize_u8(Visitor::<Self>(PhantomData))
}
}
}