use chrono::NaiveDateTime;
use serde::{self, Deserialize, Deserializer, Serializer};
const PARSE_FORMAT: &str = "%Y-%m-%dT%H:%M:%S%.f";
const SERIALIZE_FORMAT: &str = "%Y-%m-%dT%H:%M:%S%.3f";
pub fn serialize<S>(date: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = format!("{}Z", date.format(SERIALIZE_FORMAT));
serializer.serialize_str(&s)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<NaiveDateTime, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
let trimmed = s.trim_end_matches('Z');
NaiveDateTime::parse_from_str(trimmed, PARSE_FORMAT).map_err(serde::de::Error::custom)
}
pub mod option {
use chrono::NaiveDateTime;
use serde::{self, Deserialize, Deserializer, Serializer};
const PARSE_FORMAT: &str = "%Y-%m-%dT%H:%M:%S%.f";
const SERIALIZE_FORMAT: &str = "%Y-%m-%dT%H:%M:%S%.3f";
pub fn serialize<S>(date: &Option<NaiveDateTime>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match date {
Some(d) => serializer.serialize_str(&format!("{}Z", d.format(SERIALIZE_FORMAT))),
None => serializer.serialize_none(),
}
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<NaiveDateTime>, D::Error>
where
D: Deserializer<'de>,
{
let opt: Option<String> = Option::deserialize(deserializer)?;
match opt {
Some(s) => {
let trimmed = s.trim_end_matches('Z');
NaiveDateTime::parse_from_str(trimmed, PARSE_FORMAT)
.map(Some)
.map_err(serde::de::Error::custom)
}
None => Ok(None),
}
}
}