task_hookrs/
date.rs

1//
2// This Source Code Form is subject to the terms of the Mozilla Public
3// License, v. 2.0. If a copy of the MPL was not distributed with this
4// file, You can obtain one at http://mozilla.org/MPL/2.0/.
5//
6
7//! Module for wrapping chrono::naive::datetime::NaiveDateTime
8
9use std::ops::{Deref, DerefMut};
10
11use chrono::NaiveDateTime;
12use serde::de::Error as SerdeError;
13use serde::de::Visitor;
14use serde::Deserialize;
15use serde::Deserializer;
16use serde::Serialize;
17use serde::Serializer;
18
19/// Date is a NaiveDateTime-Wrapper object to be able to implement foreign traits on it
20#[derive(Clone, Debug, Hash, Eq, PartialEq)]
21pub struct Date(NaiveDateTime);
22
23impl Deref for Date {
24    type Target = NaiveDateTime;
25
26    fn deref(&self) -> &NaiveDateTime {
27        &self.0
28    }
29}
30
31impl DerefMut for Date {
32    fn deref_mut(&mut self) -> &mut NaiveDateTime {
33        &mut self.0
34    }
35}
36
37impl From<NaiveDateTime> for Date {
38    fn from(ndt: NaiveDateTime) -> Date {
39        Date(ndt)
40    }
41}
42
43/// The date-time parsing template used to parse the date time data exported by taskwarrior.
44pub static TASKWARRIOR_DATETIME_TEMPLATE: &str = "%Y%m%dT%H%M%SZ";
45
46impl Serialize for Date {
47    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
48    where
49        S: Serializer,
50    {
51        let formatted = self.0.format(TASKWARRIOR_DATETIME_TEMPLATE);
52        serializer.serialize_str(&format!("{}", formatted))
53    }
54}
55
56impl<'de> Deserialize<'de> for Date {
57    fn deserialize<D>(deserializer: D) -> Result<Date, D::Error>
58    where
59        D: Deserializer<'de>,
60    {
61        struct DateVisitor;
62
63        impl<'v> Visitor<'v> for DateVisitor {
64            type Value = Date;
65
66            fn expecting(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
67                write!(
68                    fmt,
69                    "a string which matches {}",
70                    TASKWARRIOR_DATETIME_TEMPLATE
71                )
72            }
73
74            fn visit_str<E>(self, value: &str) -> Result<Date, E>
75            where
76                E: SerdeError,
77            {
78                NaiveDateTime::parse_from_str(value, TASKWARRIOR_DATETIME_TEMPLATE)
79                    .map(Date)
80                    .map_err(|e| SerdeError::custom(e.to_string()))
81            }
82        }
83
84        deserializer.deserialize_str(DateVisitor)
85    }
86}