How to deserialise DateTime from toml configuration
Thiago Massari Guedes
Posted on April 26, 2024
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
Link to author's blog: thiagocafe/How to deserialise DateTime from toml configuration
Posted on April 26, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.