ntp_client/formats/
timestamp.rs

1use e_utils::chrono::{DateTime, TimeZone, Utc};
2use std::fmt;
3
4// NTP与UNIX时间戳差值保持不变(1900-01-01到1970-01-01)
5pub 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; // 添加 NTP 与 UNIX 时间差
23        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}
30// 核心修改点1:时间类型替换为chrono的DateTime<Utc>
31impl 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
47// 核心修改点2:格式化实现改用chrono的format方法
48impl 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")) // 等效原asctime格式[1](@ref)
52    }
53}
54
55// 数值转换保持相同逻辑
56impl 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
71// 长格式时间结构体实现
72impl 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// 测试用例改造
111#[test]
112fn timestamp_conversions() {
113    // 测试当前时间转换
114    let chrono_now = Utc::now();
115
116    // 短格式测试
117    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    // 长格式测试
128    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}