1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use chrono::{DateTime, Utc};
use serde::{self, Deserialize, Deserializer, Serializer};
pub fn serialize<S>(date: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&date.to_rfc3339())
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
let datetime = match DateTime::parse_from_rfc3339(&s) {
Ok(datetime) => datetime,
Err(error) => match error.to_string().as_str() {
"premature end of input" => {
let datetime_str = s + "Z";
DateTime::parse_from_rfc3339(&datetime_str).map_err(serde::de::Error::custom)?
}
_ => panic!("Invalid datetime"),
},
};
let datatime_utc = datetime.with_timezone(&Utc);
return Ok(datatime_utc);
}
#[cfg(test)]
mod tests {
use super::*;
use crate::utils;
use chrono::Utc;
use rstest::*;
use serde::Serialize;
#[rstest]
#[case(serde_json::json!({"datetime":"2021-11-29T17:15:51.694223Z"}))]
#[case(serde_json::json!({"datetime":"2021-11-29T17:15:51.694223"}))]
#[case(serde_json::json!({"datetime":"2021-11-29T17:15:51.694223+00:00"}))]
fn serialize_deserialize_datetime(#[case] given_datetime: serde_json::Value) {
#[derive(Serialize, Deserialize)]
struct AStruct {
#[serde(with = "utils::datetime")]
datetime: DateTime<Utc>,
}
let deserialized_struct: AStruct = serde_json::from_value(given_datetime.clone()).unwrap();
assert_eq!(deserialized_struct.datetime.timezone(), Utc);
let serialized_struct = serde_json::to_value(deserialized_struct).unwrap();
assert_eq!(
serialized_struct,
serde_json::json!({"datetime":"2021-11-29T17:15:51.694223+00:00"})
);
}
}