DEV Community

Thiago Massari Guedes
Thiago Massari Guedes

Posted on

4

How to deserialise DateTime from toml configuration

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
Enter fullscreen mode Exit fullscreen mode

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))  
    }  
}
Enter fullscreen mode Exit fullscreen mode

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()));  
    }  
}
Enter fullscreen mode Exit fullscreen mode

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

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more