Skip to content

Commit

Permalink
Merge pull request #1 from pendulum-project/time-offset
Browse files Browse the repository at this point in the history
Switch to own TimeOffset time to deal with signed offset.
  • Loading branch information
folkertdev authored Aug 10, 2023
2 parents 4628f18 + a5d3154 commit 3ab6721
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 23 deletions.
11 changes: 9 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,15 @@ pub mod unix;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Timestamp {
pub seconds: libc::time_t,
/// Nanos must be between 0 and 999999999 inclusive
pub nanos: u32,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct TimeOffset {
pub seconds: libc::time_t,
/// Nanos must be between 0 and 999999999 inclusive
pub nanos: u32,
pub subnanos: u32,
}

/// Indicate whether a leap second must be applied
Expand Down Expand Up @@ -56,7 +63,7 @@ pub trait Clock {

/// Change the current time of the clock by an offset.
/// Returns the time at which the change was applied.
fn step_clock(&self, offset: Duration) -> Result<Timestamp, Self::Error>;
fn step_clock(&self, offset: TimeOffset) -> Result<Timestamp, Self::Error>;

/// Change the indicators for upcoming leap seconds.
fn set_leap_seconds(&self, leap_status: LeapIndicator) -> Result<(), Self::Error>;
Expand Down
40 changes: 19 additions & 21 deletions src/unix.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Clock, LeapIndicator, Timestamp};
use crate::{Clock, LeapIndicator, TimeOffset, Timestamp};
use std::{
os::unix::prelude::{AsRawFd, FromRawFd, RawFd},
path::Path,
Expand Down Expand Up @@ -157,17 +157,14 @@ impl UnixClock {
}

#[cfg_attr(target_os = "linux", allow(unused))]
fn step_clock_by_timespec(&self, offset: Duration) -> Result<Timestamp, Error> {
let offset_secs = offset.as_secs();
let offset_nanos = offset.subsec_nanos();

fn step_clock_by_timespec(&self, offset: TimeOffset) -> Result<Timestamp, Error> {
let mut timespec = self.clock_gettime()?;

// see https://github.com/rust-lang/libc/issues/1848
#[cfg_attr(target_env = "musl", allow(deprecated))]
{
timespec.tv_sec += offset_secs as libc::time_t;
timespec.tv_nsec += offset_nanos as libc::c_long;
timespec.tv_sec += offset.seconds as libc::time_t;
timespec.tv_nsec += offset.nanos as libc::c_long;
}

self.clock_settime(timespec)?;
Expand All @@ -191,13 +188,13 @@ impl UnixClock {
}

#[cfg(target_os = "linux")]
fn step_clock_timex(offset: Duration) -> libc::timex {
fn step_clock_timex(offset: TimeOffset) -> libc::timex {
// we provide the offset in nanoseconds
let modes = libc::ADJ_SETOFFSET | libc::ADJ_NANO;

let time = libc::timeval {
tv_sec: offset.as_secs() as _,
tv_usec: offset.subsec_nanos() as libc::suseconds_t,
tv_sec: offset.seconds,
tv_usec: offset.nanos as libc::suseconds_t,
};

libc::timex {
Expand All @@ -208,7 +205,7 @@ impl UnixClock {
}

#[cfg(target_os = "linux")]
fn step_clock_by_timex(&self, offset: Duration) -> Result<Timestamp, Error> {
fn step_clock_by_timex(&self, offset: TimeOffset) -> Result<Timestamp, Error> {
let mut timex = Self::step_clock_timex(offset);
self.adjtime(&mut timex)?;
self.extract_current_time(&timex)
Expand Down Expand Up @@ -378,12 +375,12 @@ impl Clock for UnixClock {
}

#[cfg(target_os = "linux")]
fn step_clock(&self, offset: Duration) -> Result<Timestamp, Self::Error> {
fn step_clock(&self, offset: TimeOffset) -> Result<Timestamp, Self::Error> {
self.step_clock_by_timex(offset)
}

#[cfg(any(target_os = "freebsd", target_os = "macos"))]
fn step_clock(&self, offset: Duration) -> Result<Timestamp, Self::Error> {
fn step_clock(&self, offset: TimeOffset) -> Result<Timestamp, Self::Error> {
self.step_clock_by_timespec(offset)
}

Expand Down Expand Up @@ -537,7 +534,6 @@ fn current_time_timespec(timespec: libc::timespec, precision: Precision) -> Time
Timestamp {
seconds,
nanos: nanos as u32,
subnanos: 0,
}
}

Expand All @@ -551,11 +547,7 @@ fn current_time_timeval(timespec: libc::timeval, precision: Precision) -> Timest
.unwrap_or_default(),
};

Timestamp {
seconds,
nanos,
subnanos: 0,
}
Timestamp { seconds, nanos }
}

const EMPTY_TIMESPEC: libc::timespec = libc::timespec {
Expand Down Expand Up @@ -694,7 +686,10 @@ mod tests {
#[ignore = "requires permissions, useful for testing permissions"]
fn step_clock() {
UnixClock::CLOCK_REALTIME
.step_clock(Duration::new(0, 0))
.step_clock(TimeOffset {
seconds: 0,
nanos: 0,
})
.unwrap();
}

Expand Down Expand Up @@ -743,7 +738,10 @@ mod tests {
#[cfg(target_os = "linux")]
#[test]
fn test_step_clock() {
let offset = Duration::from_secs_f64(1.2);
let offset = TimeOffset {
seconds: 1,
nanos: 200000000,
};
let timex = UnixClock::step_clock_timex(offset);

assert_eq!(timex.modes, libc::ADJ_SETOFFSET | libc::ADJ_NANO);
Expand Down

0 comments on commit 3ab6721

Please sign in to comment.