#![cfg(feature = "serde")]
pub(crate) mod rfc3339 {
use serde::{Deserialize, Deserializer, Serialize, Serializer, de, ser};
use time::OffsetDateTime;
use time::format_description::well_known::Rfc3339;
pub(crate) fn serialize<S: Serializer>(
value: &OffsetDateTime,
serializer: S,
) -> Result<S::Ok, S::Error> {
if serializer.is_human_readable() {
let text = value.format(&Rfc3339).map_err(ser::Error::custom)?;
return serializer.serialize_str(&text);
}
value.serialize(serializer)
}
pub(crate) fn deserialize<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<OffsetDateTime, D::Error> {
if deserializer.is_human_readable() {
let text = <std::borrow::Cow<'_, str>>::deserialize(deserializer)?;
return OffsetDateTime::parse(&text, &Rfc3339).map_err(de::Error::custom);
}
OffsetDateTime::deserialize(deserializer)
}
}
pub(crate) mod rfc3339_option {
use serde::{Deserialize, Deserializer, Serializer};
use time::OffsetDateTime;
#[expect(
clippy::ref_option,
reason = "the signature `serde(with)` requires of a serialize function"
)]
pub(crate) fn serialize<S: Serializer>(
value: &Option<OffsetDateTime>,
serializer: S,
) -> Result<S::Ok, S::Error> {
match value {
Some(instant) => serializer.serialize_some(&Wrapper(*instant)),
None => serializer.serialize_none(),
}
}
pub(crate) fn deserialize<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Option<OffsetDateTime>, D::Error> {
Ok(Option::<Wrapper>::deserialize(deserializer)?.map(|w| w.0))
}
#[derive(serde::Serialize, serde::Deserialize)]
#[serde(transparent)]
struct Wrapper(#[serde(with = "super::rfc3339")] OffsetDateTime);
}
pub(crate) mod iso_date {
use serde::{Deserialize, Deserializer, Serialize, Serializer, de, ser};
use time::Date;
use time::format_description::BorrowedFormatItem;
const FORMAT: &[BorrowedFormatItem<'_>] =
time::macros::format_description!("[year]-[month]-[day]");
pub(crate) fn serialize<S: Serializer>(value: &Date, serializer: S) -> Result<S::Ok, S::Error> {
if serializer.is_human_readable() {
let text = value.format(FORMAT).map_err(ser::Error::custom)?;
return serializer.serialize_str(&text);
}
value.serialize(serializer)
}
pub(crate) fn deserialize<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Date, D::Error> {
if deserializer.is_human_readable() {
let text = <std::borrow::Cow<'_, str>>::deserialize(deserializer)?;
return Date::parse(&text, FORMAT).map_err(de::Error::custom);
}
Date::deserialize(deserializer)
}
}
pub(crate) mod iso_date_option {
use serde::{Deserialize, Deserializer, Serializer};
use time::Date;
#[expect(
clippy::ref_option,
reason = "the signature `serde(with)` requires of a serialize function"
)]
pub(crate) fn serialize<S: Serializer>(
value: &Option<Date>,
serializer: S,
) -> Result<S::Ok, S::Error> {
match value {
Some(date) => serializer.serialize_some(&Wrapper(*date)),
None => serializer.serialize_none(),
}
}
pub(crate) fn deserialize<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Option<Date>, D::Error> {
Ok(Option::<Wrapper>::deserialize(deserializer)?.map(|w| w.0))
}
#[derive(serde::Serialize, serde::Deserialize)]
#[serde(transparent)]
struct Wrapper(#[serde(with = "super::iso_date")] Date);
}