use chrono::{DateTime, NaiveDate, TimeZone, Utc};
use serde::{Deserialize, Deserializer};
pub fn deserialize_date<'de, D>(deserializer: D) -> Result<Option<DateTime<Utc>>, D::Error>
where
D: Deserializer<'de>,
{
let s: Option<String> = Option::deserialize(deserializer)?;
let Some(date_str) = s else {
return Ok(None);
};
if let Ok(dt) = DateTime::parse_from_rfc3339(&date_str) {
return Ok(Some(dt.with_timezone(&Utc)));
}
if let Ok(nd) = NaiveDate::parse_from_str(&date_str, "%Y-%m-%d") {
let midnight = nd
.and_hms_opt(0, 0, 0)
.expect("midnight is always a valid time");
return Ok(Some(Utc.from_utc_datetime(&midnight)));
}
Ok(None)
}
#[derive(Debug, Deserialize, Clone)]
pub struct FrontMatter {
pub title: String,
#[serde(deserialize_with = "deserialize_date")]
pub date: Option<DateTime<Utc>>,
pub author: Option<String>,
pub description: Option<String>,
}