ntp-client 0.1.0

The ntp-client is a Rust library designed for interacting with NTP (Network Time Protocol) servers. It enables developers to easily obtain accurate time information from NTP servers. This can be applied in scenarios such as calibrating system time and performing time synchronization. The library offers a simple and user - friendly API, and also features good performance and stability.
Documentation
use e_utils::chrono::{DateTime, TimeZone, Utc};
use std::fmt;

// NTP与UNIX时间戳差值保持不变(1900-01-01到1970-01-01)
pub static EPOCH_DELTA: i64 = 2208988800i64;
static NTP_SCALE: f64 = 4294967295.0_f64;

#[derive(Debug, PartialEq, Default, Copy, Clone)]
pub struct ShortFormat {
    pub sec: u16,
    pub frac: u16,
}

#[derive(Debug, PartialEq, Default, Copy, Clone)]
pub struct TimestampFormat {
    pub sec: u32,
    pub frac: u32,
}
impl TimestampFormat {
    pub fn now() -> Self {
        let now = e_utils::chrono::Utc::now();
        let sec = now.timestamp() + EPOCH_DELTA; // 添加 NTP 与 UNIX 时间差
        let frac = (now.timestamp_subsec_nanos() as f64 * NTP_SCALE / 1e9) as u32;
        TimestampFormat {
            sec: sec as u32,
            frac,
        }
    }
}
// 核心修改点1:时间类型替换为chrono的DateTime<Utc>
impl From<ShortFormat> for DateTime<Utc> {
    fn from(t: ShortFormat) -> Self {
        let total_secs = t.sec as i64 - EPOCH_DELTA;
        let nanos = (t.frac as f64 / NTP_SCALE * 1e9) as u32;
        Utc.timestamp_opt(total_secs, nanos).unwrap()
    }
}

impl From<DateTime<Utc>> for ShortFormat {
    fn from(dt: DateTime<Utc>) -> Self {
        let sec = (dt.timestamp() + EPOCH_DELTA) as u16;
        let frac = (dt.timestamp_subsec_nanos() as f64 * NTP_SCALE / 1e9) as u16;
        ShortFormat { sec, frac }
    }
}

// 核心修改点2:格式化实现改用chrono的format方法
impl fmt::Display for ShortFormat {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let dt: DateTime<Utc> = (*self).into();
        write!(f, "{}", dt.format("%a %b %e %T %Y")) // 等效原asctime格式[1](@ref)
    }
}

// 数值转换保持相同逻辑
impl From<ShortFormat> for u32 {
    fn from(t: ShortFormat) -> u32 {
        (t.sec as u32) << 16 | t.frac as u32
    }
}

impl From<u32> for ShortFormat {
    fn from(t: u32) -> ShortFormat {
        ShortFormat {
            sec: (t >> 16) as u16,
            frac: t as u16,
        }
    }
}

// 长格式时间结构体实现
impl From<TimestampFormat> for DateTime<Utc> {
    fn from(t: TimestampFormat) -> Self {
        let total_secs = t.sec as i64 - EPOCH_DELTA;
        let nanos = (t.frac as f64 / NTP_SCALE * 1e9) as u32;
        Utc.timestamp_opt(total_secs, nanos).unwrap()
    }
}

impl From<DateTime<Utc>> for TimestampFormat {
    fn from(dt: DateTime<Utc>) -> Self {
        let sec = (dt.timestamp() + EPOCH_DELTA) as u32;
        let frac = (dt.timestamp_subsec_nanos() as f64 * NTP_SCALE / 1e9) as u32;
        TimestampFormat { sec, frac }
    }
}

impl fmt::Display for TimestampFormat {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let dt: DateTime<Utc> = (*self).into();
        write!(f, "{}", dt.format("%a %b %e %T %Y"))
    }
}

impl From<TimestampFormat> for u64 {
    fn from(t: TimestampFormat) -> u64 {
        (t.sec as u64) << 32 | t.frac as u64
    }
}

impl From<u64> for TimestampFormat {
    fn from(t: u64) -> TimestampFormat {
        TimestampFormat {
            sec: (t >> 32) as u32,
            frac: t as u32,
        }
    }
}

// 测试用例改造
#[test]
fn timestamp_conversions() {
    // 测试当前时间转换
    let chrono_now = Utc::now();

    // 短格式测试
    let short_format: ShortFormat = chrono_now.into();
    let converted_back: DateTime<Utc> = short_format.into();
    assert!(
        (chrono_now - converted_back)
            .num_nanoseconds()
            .unwrap()
            .abs()
            < 1000
    );

    // 长格式测试
    let ts_format: TimestampFormat = chrono_now.into();
    let converted_back: DateTime<Utc> = ts_format.into();
    assert!(
        (chrono_now - converted_back)
            .num_nanoseconds()
            .unwrap()
            .abs()
            < 1000
    );
}