xray_lite/
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 From<Seconds> for Duration {
44    fn from(s: Seconds) -> Self {
45        Duration::new(s.0.trunc() as u64, (s.0.fract() * 1.0e9) as u32)
46    }
47}
48
49struct SecondsVisitor;
50
51impl<'de> de::Visitor<'de> for SecondsVisitor {
52    type Value = Seconds;
53
54    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
55        formatter.write_str("a string value")
56    }
57    fn visit_f64<E>(self, value: f64) -> Result<Seconds, E>
58    where
59        E: de::Error,
60    {
61        Ok(Seconds(value))
62    }
63}
64
65impl ser::Serialize for Seconds {
66    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
67    where
68        S: Serializer,
69    {
70        let Seconds(seconds) = self;
71        serializer.serialize_f64(*seconds)
72    }
73}
74
75impl<'de> de::Deserialize<'de> for Seconds {
76    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
77    where
78        D: de::Deserializer<'de>,
79    {
80        deserializer.deserialize_f64(SecondsVisitor)
81    }
82}
83
84#[cfg(test)]
85mod tests {
86    use super::Seconds;
87
88    #[test]
89    fn seconds_serialize() {
90        assert_eq!(
91            serde_json::to_string(&Seconds(1_545_136_342.711_932)).expect("failed to serialize"),
92            "1545136342.711932"
93        );
94    }
95
96    #[test]
97    fn seconds_deserialize() {
98        assert_eq!(
99            serde_json::from_slice::<Seconds>(b"1545136342.711932").expect("failed to serialize"),
100            Seconds(1_545_136_342.711_932)
101        );
102    }
103}