xntp/
lib.rs

1//! # XNtp
2//!
3//! `xntp` is a client of ntp to get net time and format
4//! 
5//! 
6//! # Example 
7//! ```rust
8//! use xntp::NtpClient;
9//! fn main(){
10//!     let client = NtpClient::new();
11//!     let res = client.request("ntp.aliyun.com");
12//!     println!("{}", res.unix_time);
13//!     println!("{}", res.format_time("%Y-%m-%d %H:%M:%S"));
14//! }
15//! 
16//! ```
17
18
19use std::net::UdpSocket;
20use byteorder::{ BigEndian, ReadBytesExt };
21use std::io::{ Cursor, Seek, SeekFrom };
22use chrono::prelude::*;
23
24pub struct NtpClient;
25impl NtpClient {
26    pub fn new() -> NtpClient {
27        NtpClient
28    }
29    pub fn request(self, server: &str) -> Response {
30        let client = UdpSocket::bind("0.0.0.0:0").unwrap();
31        client.connect(format!("{server}:123")).unwrap();
32        let mut request_data = vec![0;48];
33        request_data[0] = 0x1b;
34        client.send(&request_data).unwrap();
35        let mut buf = [0; 48];
36        client.recv(&mut buf).unwrap();
37        let ntp_second = self.unpack_ntp_data(&buf);
38        let unix_second = ntp_second - 2208988800;
39        let response = Response {
40            unix_time: unix_second,
41        };
42        response
43    }
44    fn unpack_ntp_data(self, buffer: &[u8; 48]) -> u64 {
45        let mut reader = Cursor::new(buffer);
46        reader.seek(SeekFrom::Current(40)).unwrap();
47        let ntp_second = reader.read_u32::<BigEndian>().unwrap();
48        u64::from(ntp_second)
49    }
50}
51
52pub struct Response {
53    pub unix_time: u64,
54}
55
56impl Response {
57    pub fn format_time(self, fmt: &str) -> String {
58        // time_format::strftime_utc(fmt, self.unix_time as i64).unwrap()
59        let dt = DateTime::<Utc>::from_utc(
60            NaiveDateTime::from_timestamp_opt(
61                self.unix_time as i64,
62                ((self.unix_time % 1000) as u32) * 1_000_000
63            ).unwrap(),
64            Utc
65        );
66        let shanghai = FixedOffset::east_opt(8 * 3600).unwrap();
67        format!("{}", dt.with_timezone(&shanghai).format(fmt))
68    }
69}
70
71#[test]
72fn test() {
73    let client = NtpClient::new();
74    let res = client.request("ntp.aliyun.com");
75    println!("{}", res.unix_time);
76    println!("{}", res.format_time("%Y-%m-%d %H:%M:%S"));
77}