ntp_client/formats/
timestamp.rs1use e_utils::chrono::{DateTime, TimeZone, Utc};
2use std::fmt;
3
4pub static EPOCH_DELTA: i64 = 2208988800i64;
6static NTP_SCALE: f64 = 4294967295.0_f64;
7
8#[derive(Debug, PartialEq, Default, Copy, Clone)]
9pub struct ShortFormat {
10 pub sec: u16,
11 pub frac: u16,
12}
13
14#[derive(Debug, PartialEq, Default, Copy, Clone)]
15pub struct TimestampFormat {
16 pub sec: u32,
17 pub frac: u32,
18}
19impl TimestampFormat {
20 pub fn now() -> Self {
21 let now = e_utils::chrono::Utc::now();
22 let sec = now.timestamp() + EPOCH_DELTA; let frac = (now.timestamp_subsec_nanos() as f64 * NTP_SCALE / 1e9) as u32;
24 TimestampFormat {
25 sec: sec as u32,
26 frac,
27 }
28 }
29}
30impl From<ShortFormat> for DateTime<Utc> {
32 fn from(t: ShortFormat) -> Self {
33 let total_secs = t.sec as i64 - EPOCH_DELTA;
34 let nanos = (t.frac as f64 / NTP_SCALE * 1e9) as u32;
35 Utc.timestamp_opt(total_secs, nanos).unwrap()
36 }
37}
38
39impl From<DateTime<Utc>> for ShortFormat {
40 fn from(dt: DateTime<Utc>) -> Self {
41 let sec = (dt.timestamp() + EPOCH_DELTA) as u16;
42 let frac = (dt.timestamp_subsec_nanos() as f64 * NTP_SCALE / 1e9) as u16;
43 ShortFormat { sec, frac }
44 }
45}
46
47impl fmt::Display for ShortFormat {
49 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
50 let dt: DateTime<Utc> = (*self).into();
51 write!(f, "{}", dt.format("%a %b %e %T %Y")) }
53}
54
55impl From<ShortFormat> for u32 {
57 fn from(t: ShortFormat) -> u32 {
58 (t.sec as u32) << 16 | t.frac as u32
59 }
60}
61
62impl From<u32> for ShortFormat {
63 fn from(t: u32) -> ShortFormat {
64 ShortFormat {
65 sec: (t >> 16) as u16,
66 frac: t as u16,
67 }
68 }
69}
70
71impl From<TimestampFormat> for DateTime<Utc> {
73 fn from(t: TimestampFormat) -> Self {
74 let total_secs = t.sec as i64 - EPOCH_DELTA;
75 let nanos = (t.frac as f64 / NTP_SCALE * 1e9) as u32;
76 Utc.timestamp_opt(total_secs, nanos).unwrap()
77 }
78}
79
80impl From<DateTime<Utc>> for TimestampFormat {
81 fn from(dt: DateTime<Utc>) -> Self {
82 let sec = (dt.timestamp() + EPOCH_DELTA) as u32;
83 let frac = (dt.timestamp_subsec_nanos() as f64 * NTP_SCALE / 1e9) as u32;
84 TimestampFormat { sec, frac }
85 }
86}
87
88impl fmt::Display for TimestampFormat {
89 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90 let dt: DateTime<Utc> = (*self).into();
91 write!(f, "{}", dt.format("%a %b %e %T %Y"))
92 }
93}
94
95impl From<TimestampFormat> for u64 {
96 fn from(t: TimestampFormat) -> u64 {
97 (t.sec as u64) << 32 | t.frac as u64
98 }
99}
100
101impl From<u64> for TimestampFormat {
102 fn from(t: u64) -> TimestampFormat {
103 TimestampFormat {
104 sec: (t >> 32) as u32,
105 frac: t as u32,
106 }
107 }
108}
109
110#[test]
112fn timestamp_conversions() {
113 let chrono_now = Utc::now();
115
116 let short_format: ShortFormat = chrono_now.into();
118 let converted_back: DateTime<Utc> = short_format.into();
119 assert!(
120 (chrono_now - converted_back)
121 .num_nanoseconds()
122 .unwrap()
123 .abs()
124 < 1000
125 );
126
127 let ts_format: TimestampFormat = chrono_now.into();
129 let converted_back: DateTime<Utc> = ts_format.into();
130 assert!(
131 (chrono_now - converted_back)
132 .num_nanoseconds()
133 .unwrap()
134 .abs()
135 < 1000
136 );
137}