use crate::errors::FejError; use chrono::{DateTime, NaiveDate, TimeZone}; use chrono_tz::{Europe::Brussels, Tz}; use rocket::{http::RawStr, request::FromFormValue}; use serde::{ser::Serializer, 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); 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), } } } 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::*; /// Tests catching a string with an invalid date #[test] fn test_invalid_date() { let val = "2012-13-12"; let date = BasicDate::try_from(val); assert_eq!(date, Err(FejError::InvalidArgument)); } }