azure_core/date/
iso8601.rsuse crate::error::{ErrorKind, ResultExt};
use serde::{de, Deserialize, Deserializer, Serializer};
use time::{
format_description::well_known::{
iso8601::{Config, EncodedConfig, TimePrecision},
Iso8601,
},
OffsetDateTime, UtcOffset,
};
const SERDE_CONFIG: EncodedConfig = Config::DEFAULT
.set_year_is_six_digits(false)
.set_time_precision(TimePrecision::Second {
decimal_digits: None,
})
.encode();
pub fn parse_iso8601(s: &str) -> crate::Result<OffsetDateTime> {
OffsetDateTime::parse(s, &Iso8601::<SERDE_CONFIG>)
.with_context(ErrorKind::DataConversion, || {
format!("unable to parse iso8601 date '{s}")
})
}
pub fn to_iso8601(date: &OffsetDateTime) -> crate::Result<String> {
date.format(&Iso8601::<SERDE_CONFIG>)
.with_context(ErrorKind::DataConversion, || {
format!("unable to format date '{date:?}")
})
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
parse_iso8601(&s).map_err(de::Error::custom)
}
pub fn serialize<S>(date: &OffsetDateTime, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
date.to_offset(UtcOffset::UTC);
let as_str = to_iso8601(date).map_err(serde::ser::Error::custom)?;
serializer.serialize_str(&as_str)
}
pub mod option {
use crate::date::iso8601::{parse_iso8601, to_iso8601};
use serde::{Deserialize, Deserializer, Serializer};
use time::OffsetDateTime;
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<OffsetDateTime>, D::Error>
where
D: Deserializer<'de>,
{
let s: Option<String> = Option::deserialize(deserializer)?;
s.map(|s| parse_iso8601(&s).map_err(serde::de::Error::custom))
.transpose()
}
pub fn serialize<S>(date: &Option<OffsetDateTime>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if let Some(date) = date {
serializer.serialize_str(&to_iso8601(date).map_err(serde::ser::Error::custom)?)
} else {
serializer.serialize_none()
}
}
}