69 lines
1.7 KiB
Rust
69 lines
1.7 KiB
Rust
|
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<Tz>);
|
||
|
|
||
|
impl<'v> FromFormValue<'v> for BasicDate {
|
||
|
type Error = &'v RawStr;
|
||
|
|
||
|
fn from_form_value(form_value: &'v RawStr) -> Result<BasicDate, Self::Error> {
|
||
|
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<BasicDate, Self::Error> {
|
||
|
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||
|
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));
|
||
|
}
|
||
|
}
|