xray_tracing/
epoch.rs

1use serde::{de, ser, Serializer};
2use std::{
3    fmt,
4    time::{Duration, SystemTime, UNIX_EPOCH},
5};
6
7/// Represents fractional seconds since the epoch
8/// These can be derived from std::time::Duration and be converted
9/// too std::time::Duration
10///
11/// A Default implementation is provided which yields the number of seconds since the epoch from
12/// the system time's `now` value
13#[derive(Debug, PartialEq)]
14pub struct Seconds(pub(crate) f64);
15
16impl Seconds {
17    /// return the current time in seconds since the unix epoch (1-1-1970 midnight)
18    pub fn now() -> Self {
19        SystemTime::now()
20            .duration_since(UNIX_EPOCH)
21            .unwrap_or_default()
22            .into()
23    }
24
25    /// truncate epoc time to remove fractional seconds
26    pub fn trunc(&self) -> u64 {
27        self.0.trunc() as u64
28    }
29}
30
31impl Default for Seconds {
32    fn default() -> Self {
33        Seconds::now()
34    }
35}
36
37impl From<Duration> for Seconds {
38    fn from(d: Duration) -> Self {
39        Seconds(d.as_secs() as f64 + (f64::from(d.subsec_nanos()) / 1.0e9))
40    }
41}
42
43impl Into<Duration> for Seconds {
44    fn into(self) -> Duration {
45        let Seconds(secs) = self;
46        Duration::new(secs.trunc() as u64, (secs.fract() * 1.0e9) as u32)
47    }
48}
49
50struct SecondsVisitor;
51
52impl<'de> de::Visitor<'de> for SecondsVisitor {
53    type Value = Seconds;
54
55    fn expecting(
56        &self,
57        formatter: &mut fmt::Formatter,
58    ) -> fmt::Result {
59        formatter.write_str("a string value")
60    }
61    fn visit_f64<E>(
62        self,
63        value: f64,
64    ) -> Result<Seconds, E>
65    where
66        E: de::Error,
67    {
68        Ok(Seconds(value))
69    }
70}
71
72impl ser::Serialize for Seconds {
73    fn serialize<S>(
74        &self,
75        serializer: S,
76    ) -> Result<S::Ok, S::Error>
77    where
78        S: Serializer,
79    {
80        let Seconds(seconds) = self;
81        serializer.serialize_f64(*seconds)
82    }
83}
84
85impl<'de> de::Deserialize<'de> for Seconds {
86    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
87    where
88        D: de::Deserializer<'de>,
89    {
90        deserializer.deserialize_f64(SecondsVisitor)
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use super::Seconds;
97
98    #[test]
99    fn seconds_serialize() {
100        assert_eq!(
101            serde_json::to_string(&Seconds(1_545_136_342.711_932)).expect("failed to serialize"),
102            "1545136342.711932"
103        );
104    }
105
106    #[test]
107    fn seconds_deserialize() {
108        assert_eq!(
109            serde_json::from_slice::<Seconds>(b"1545136342.711932").expect("failed to serialize"),
110            Seconds(1_545_136_342.711_932)
111        );
112    }
113}