1use 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#[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
43pub 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}