use crate::errors::FejError; use chrono::{DateTime, NaiveDate, TimeZone}; use chrono_tz::Europe::Brussels; use chrono_tz::Tz; use rocket::http::RawStr; use rocket::request::FromFormValue; use serde::ser::Serializer; use serde::Serialize; use std::convert::TryFrom; /// This class is a simple wrapper around chrono's DateTime. Its sole purpose /// is to avoid error E0117. #[derive(Debug, PartialEq)] pub struct BasicDate(pub DateTime); /// This allows us to use BasicDate as a query parameter in our routes. impl<'v> FromFormValue<'v> for BasicDate { type Error = &'v RawStr; fn from_form_value(form_value: &'v RawStr) -> Result { match BasicDate::try_from(form_value.as_str()) { Err(_) => Err(form_value), Ok(date) => Ok(date), } } } /// This is used to serialize BasicDate. impl TryFrom<&str> for BasicDate { type Error = FejError; fn try_from(s: &str) -> Result { let naive_date = NaiveDate::parse_from_str(s, "%Y-%m-%d")?; Ok(BasicDate( Brussels .from_local_datetime(&naive_date.and_hms(0, 0, 0)) .single() .ok_or(FejError::InvalidArgument)?, )) } } impl From<&BasicDate> for String { fn from(date: &BasicDate) -> String { format!("{}", date.0.format("%Y-%m-%d")) } } impl Serialize for BasicDate { fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.serialize_str(&String::from(self)) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_invalid_date() { let val = "2012-13-12"; let date = BasicDate::try_from(val); assert_eq!(date, Err(FejError::InvalidArgument)); } }