pub mod date_serde {
use time::{format_description::BorrowedFormatItem, macros::format_description, Date};
const DATE_FMT: &[BorrowedFormatItem<'_>] = format_description!("[year]-[month]-[day]");
pub fn serialize<S: serde::Serializer>(date: &Date, s: S) -> Result<S::Ok, S::Error> {
let text = date.format(DATE_FMT).map_err(serde::ser::Error::custom)?;
s.serialize_str(&text)
}
pub fn deserialize<'de, D: serde::Deserializer<'de>>(d: D) -> Result<Date, D::Error> {
struct Visitor;
impl<'de> serde::de::Visitor<'de> for Visitor {
type Value = Date;
fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("an ISO 8601 date string (YYYY-MM-DD)")
}
fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Date, E> {
Date::parse(v, DATE_FMT).map_err(E::custom)
}
}
d.deserialize_str(Visitor)
}
}
pub mod opt_date_serde {
use time::{format_description::BorrowedFormatItem, macros::format_description, Date};
const DATE_FMT: &[BorrowedFormatItem<'_>] = format_description!("[year]-[month]-[day]");
pub fn serialize<S: serde::Serializer>(val: &Option<Date>, s: S) -> Result<S::Ok, S::Error> {
match val {
None => s.serialize_none(),
Some(d) => {
let text = d.format(DATE_FMT).map_err(serde::ser::Error::custom)?;
s.serialize_some(&text)
}
}
}
pub fn deserialize<'de, D: serde::Deserializer<'de>>(d: D) -> Result<Option<Date>, D::Error> {
struct Visitor;
impl<'de> serde::de::Visitor<'de> for Visitor {
type Value = Option<Date>;
fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("an ISO 8601 date string (YYYY-MM-DD) or null")
}
fn visit_none<E: serde::de::Error>(self) -> Result<Option<Date>, E> {
Ok(None)
}
fn visit_unit<E: serde::de::Error>(self) -> Result<Option<Date>, E> {
Ok(None)
}
fn visit_some<D2: serde::Deserializer<'de>>(
self,
d: D2,
) -> Result<Option<Date>, D2::Error> {
super::date_serde::deserialize(d).map(Some)
}
}
d.deserialize_option(Visitor)
}
}