An RFC 5905 compliant Simple Network Time Protocol (SNTP) client library for Rust.
rsntp
provides an API to synchronize time with SNTPv4 time servers with the following features:
* Provides both a synchronous (blocking) and an (optional) asynchronous, tokio
based API
* Optional support for time and date crates chrono
and time
(chrono
is enabled by
default)
* IPv6 support
Add this to your Cargo.toml
:
toml
[dependencies]
rsntp = "3.0.2"
Obtain the current local time with the blocking API:
```rust use rsntp::SntpClient; use chrono::{DateTime, Local};
let client = SntpClient::new(); let result = client.synchronize("pool.ntp.org").unwrap();
let localtime: DateTime
println!("Current time is: {}", local_time); ```
You can also use the asynchronous API to do the same:
```rust use rsntp::AsyncSntpClient; use chrono::{DateTime, Local, Utc};
async fn local_time() -> DateTime
DateTime::from(result.datetime().intochronodatetime().unwrap()) } ```
Version 3.0 made core code independent of time and date crates and added support for the time
crate.
This led to some breaking API changes, SynchronizationResult
methods will return with wrappers
struct instead of chrono
ones. Those wrapper structs has TryInto
implementation and helper
methods to convert them to chrono
format.
To convert old code, replace
rust
let datetime = result.datetime();
with
rust
let datetime = result.datetime().into_chrono_datetime().unwrap();
or with
rust
let datetime: chrono::DateTime<Utc> = result.datetime().try_into().unwrap();
The same applies to Duration
s returned by SynchronizationResult
.
rsntp
supports returning time and date data in different formats. Currently the format of
the two most popular time and date handling crates supported: chrono
and time
.
By default, chrono
is enabled, but you can add time
support with a feature:
```rust use rsntp::SntpClient;
let client = SntpClient::new(); let result = client.synchronize("pool.ntp.org").unwrap();
let utctime = result .datetime() .intooffsetdatetime() .unwrap();
println!("UTC time is: {}", utc_time); ```
Support for both crates can be enabled independently; you can even enable both at the same time.
The asynchronous API is enabled by default, but you can disable it. Disabling it
has the advantage that it removes the dependency to tokio
, which reduces
the amount of dependencies significantly.
toml
[dependencies]
rsntp = { version = "3.0.2", default-features = false, features = ["chrono"] }
rsntp
assumes that system clock is monotonic and stable. This is especially important
with the SynchronizationResult::datetime()
method, as SynchronizationResult
stores just
an offset to the system clock. If the system clock is changed between synchronization
and the call to this method, then offset will not be valid anymore and some undefined result
will be returned.
rsntp
supports IPv6, but for compatibility reasons, it binds its UDP socket to an
IPv4 address (0.0.0.0) by default. That might prevent synchronization with IPv6 servers.
To use IPv6, you need to set an IPv6 bind address:
```rust use rsntp::{Config, SntpClient}; use std::net::Ipv6Addr;
let config = Config::default().bindaddress((Ipv6Addr::UNSPECIFIED, 0).into()); let client = SntpClient::withconfig(config);
let result = client.synchronize("2.pool.ntp.org").unwrap();
let unixtimestamputc = result.datetime().unix_timestamp(); ```