rust_ocpp/v2_0_1/helpers/
datetime_rfc3339.rs1use chrono::{DateTime, SecondsFormat, Utc};
2use serde::{Deserialize, Deserializer, Serializer};
3pub fn serialize<S>(date: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
4where
5 S: Serializer,
6{
7 serializer.serialize_str(&date.to_rfc3339_opts(SecondsFormat::Millis, true))
8}
9
10pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
11where
12 D: Deserializer<'de>,
13{
14 let s: String = Deserialize::deserialize(deserializer)?;
15 DateTime::parse_from_rfc3339(&s)
16 .map(|dt| dt.with_timezone(&Utc))
17 .map_err(serde::de::Error::custom)
18}
19
20pub mod option {
21 use chrono::{DateTime, SecondsFormat, Utc};
22 use serde::{self, Deserialize, Deserializer, Serializer};
23
24 pub fn serialize<S>(date: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
25 where
26 S: Serializer,
27 {
28 match date {
29 Some(dt) => serializer.serialize_str(&dt.to_rfc3339_opts(SecondsFormat::Millis, true)),
30 None => serializer.serialize_none(),
31 }
32 }
33
34 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<DateTime<Utc>>, D::Error>
35 where
36 D: Deserializer<'de>,
37 {
38 let opt = Option::<String>::deserialize(deserializer)?;
39 match opt {
40 Some(s) => DateTime::parse_from_rfc3339(&s)
41 .map(|dt| Some(dt.with_timezone(&Utc)))
42 .map_err(serde::de::Error::custom),
43 None => Ok(None),
44 }
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51 use chrono::{TimeZone, Utc};
52 use serde_json;
53
54 #[test]
55 fn test_serialize_deserialize_datetime() {
56 let naive = Utc
57 .with_ymd_and_hms(2023, 9, 3, 12, 34, 56)
58 .unwrap()
59 .naive_utc();
60 let naive = naive
61 .checked_add_signed(chrono::Duration::milliseconds(789))
62 .unwrap();
63 let dt: DateTime<Utc> = DateTime::from_naive_utc_and_offset(naive, Utc);
64 let json = serde_json::to_string(&dt).unwrap();
65 let deserialized: DateTime<Utc> = serde_json::from_str(&json).unwrap();
66 assert_eq!(dt, deserialized);
67 }
68
69 #[test]
70 fn test_serialize_deserialize_option_some() {
71 let naive = Utc
72 .with_ymd_and_hms(2023, 9, 3, 12, 34, 56)
73 .unwrap()
74 .naive_utc();
75 let naive = naive
76 .checked_add_signed(chrono::Duration::milliseconds(789))
77 .unwrap();
78 let dt: DateTime<Utc> = DateTime::from_naive_utc_and_offset(naive, Utc);
79 let opt_dt = Some(dt);
80 let json = serde_json::to_string(&opt_dt).unwrap();
81 let deserialized: Option<DateTime<Utc>> =
82 option::deserialize(&mut serde_json::Deserializer::from_str(&json)).unwrap();
83 assert_eq!(opt_dt, deserialized);
84 }
85
86 #[test]
87 fn test_serialize_deserialize_option_none() {
88 let opt_dt: Option<DateTime<Utc>> = None;
89 let json = serde_json::to_string(&opt_dt).unwrap();
90 let deserialized: Option<DateTime<Utc>> =
91 option::deserialize(&mut serde_json::Deserializer::from_str(&json)).unwrap();
92 assert_eq!(opt_dt, deserialized);
93 }
94}