holochain_timestamp/
human.rs

1use crate::{DateTime, Timestamp};
2use serde::{Deserialize, Serialize};
3use std::convert::TryFrom;
4
5/// A human-readable timestamp which is represented/serialized as an RFC3339
6/// when possible, and a microsecond integer count otherwise.
7/// Both representations can be deserialized to this type.
8#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
9#[serde(untagged)]
10pub enum HumanTimestamp {
11    /// A microsecond resolution [`Timestamp`].
12    Micros(Timestamp),
13    /// A RFC3339 [`DateTime`](chrono::DateTime).
14    RFC3339(DateTime),
15}
16
17impl From<Timestamp> for HumanTimestamp {
18    fn from(t: Timestamp) -> Self {
19        DateTime::try_from(t)
20            .map(Self::RFC3339)
21            .unwrap_or_else(|_| Self::Micros(t))
22    }
23}
24
25impl From<DateTime> for HumanTimestamp {
26    fn from(t: DateTime) -> Self {
27        Self::RFC3339(t)
28    }
29}
30
31impl From<HumanTimestamp> for Timestamp {
32    fn from(h: HumanTimestamp) -> Self {
33        match h {
34            HumanTimestamp::Micros(t) => t,
35            HumanTimestamp::RFC3339(d) => d.into(),
36        }
37    }
38}
39
40impl From<&HumanTimestamp> for Timestamp {
41    fn from(h: &HumanTimestamp) -> Self {
42        match h {
43            HumanTimestamp::Micros(t) => *t,
44            HumanTimestamp::RFC3339(d) => d.into(),
45        }
46    }
47}
48
49impl PartialEq for HumanTimestamp {
50    fn eq(&self, other: &Self) -> bool {
51        Timestamp::from(self) == Timestamp::from(other)
52    }
53}
54
55impl Eq for HumanTimestamp {}
56
57#[cfg(test)]
58mod tests {
59    use std::str::FromStr;
60
61    use super::*;
62    use holochain_serialized_bytes::{holochain_serial, SerializedBytes};
63
64    holochain_serial!(HumanTimestamp);
65
66    #[test]
67    fn human_timestamp_conversions() {
68        let show = |v| format!("{:?}", v);
69        let s = "2022-02-11T23:05:19.470323Z";
70        let t = Timestamp::from_str(s).unwrap();
71        let h = HumanTimestamp::from(t);
72        let sb = SerializedBytes::try_from(h).unwrap();
73        let ser = show(&sb);
74        assert_eq!(ser, format!("\"{}\"", s));
75        let h2 = HumanTimestamp::try_from(sb).unwrap();
76        let t2 = Timestamp::from(h2);
77        assert_eq!(t, t2);
78    }
79}