When implementing a new configuration parameter for Texted, I needed something to represent the date the blog started.
When looking into the TOML website, I was fortunate to discover that it has a data type for dates, so I could create the new parameter
blog_start_date = 2016-06-25
However, my fortune was gone as I found that the Toml crate does not support deserialising.
First, I tried to find if any other crate implemented this, but I found nothing that worked and most of them were over complicated for my use case.
Then I thought, I am pretty sure I am not the only one with this need and with some searching, I found in Arnau Siches website a nice solution for what I needed and I am sharing here a slightly modified version of their solution
use std::str::FromStr;
use chrono::{NaiveDate, ParseError};
use serde::Deserialize;
// Code adapted from https://www.seachess.net/notes/toml-dates/
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct TomlDate(pub NaiveDate);
impl<'de> Deserialize<'de> for TomlDate {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::Error;
let value = toml::value::Datetime::deserialize(deserializer)?;
let date = TomlDate::from_str(&value.to_string()).map_err(Error::custom)?;
Ok(date)
}
}
impl FromStr for TomlDate {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let naive = NaiveDate::from_str(s)?;
Ok(Self(naive))
}
}
Of course, one small unit test to make sure it works.
#[cfg(test)]
mod tests {
use serde::Deserialize;
use super::*;
#[derive(Deserialize)]
pub struct Personal {
pub activity_start_year: i32,
pub blog_start_date: TomlDate,
}
#[derive(Deserialize)]
pub struct Config {
pub personal: Personal,
}
#[test]
fn test_date_time() {
let toml_str = r##"
[personal]
activity_start_year = 2000
blog_start_date = 2024-04-22
"##;
let cfg: Config = toml::from_str::<Config>(toml_str).unwrap();
assert_eq!(cfg.personal.blog_start_date, TomlDate(NaiveDate::from_ymd_opt(2024, 04, 22).unwrap()));
}
}
To conclude, please note that this code was adapted from a CC BY-NC 4.0 license