1use chrono::{DateTime, SecondsFormat, Utc};
2use serde::de::{Error, Unexpected, Visitor};
3use serde::{Deserializer, Serializer};
4use std::fmt;
5
6struct DateTimeVisitor;
7
8pub fn serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
9where
10 S: Serializer,
11{
12 serializer.serialize_str(dt.to_rfc3339_opts(SecondsFormat::Millis, true).as_str())
13}
14
15pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
16where
17 D: Deserializer<'de>,
18{
19 d.deserialize_str(DateTimeVisitor)
20}
21
22impl<'de> Visitor<'de> for DateTimeVisitor {
23 type Value = DateTime<Utc>;
24
25 fn expecting(&self, w: &mut fmt::Formatter) -> fmt::Result {
26 write!(w, "date and time in ISO 8601")
27 }
28
29 fn visit_borrowed_str<E>(self, value: &'de str) -> Result<DateTime<Utc>, E>
31 where
32 E: Error,
33 {
34 Ok(DateTime::parse_from_rfc3339(value)
35 .map_err(|_| Error::invalid_value(Unexpected::Str(value), &self))?
36 .with_timezone(&Utc))
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43 use chrono::Utc;
44 use serde::{Deserialize, Serialize};
45
46 #[derive(Debug, Serialize, Deserialize, PartialEq)]
47 struct Test {
48 #[serde(with = "super")]
49 time: DateTime<Utc>,
50 }
51
52 #[test]
53 fn test_deserialize() {
54 let data = r#"{"time":"2020-02-01T03:16:46.229Z"}"#;
55 let expect = Test {
56 time: DateTime::from_timestamp(1_580_527_006, 229_000_000).unwrap(),
57 };
58
59 assert_eq!(serde_json::from_str::<Test>(data).unwrap(), expect);
60 }
61
62 #[test]
63 fn test_serialize() {
64 let data = Test {
65 time: DateTime::from_timestamp(1_580_527_006, 229_000_000).unwrap(),
66 };
67 let expect = r#"{"time":"2020-02-01T03:16:46.229Z"}"#;
68
69 assert_eq!(serde_json::to_string(&data).unwrap(), expect);
70 }
71}