Revision control

Copy as Markdown

Other Tools

use std::time::SystemTime;
use crate::Duration;
/// Sealed trait to prevent downstream implementations.
mod sealed {
/// A trait that cannot be implemented by downstream users.
pub trait Sealed: Sized {}
impl Sealed for std::time::SystemTime {}
}
/// An extension trait for [`std::time::SystemTime`] that adds methods for
/// [`time::Duration`](Duration)s.
pub trait SystemTimeExt: sealed::Sealed {
/// Adds the given [`Duration`] to the [`SystemTime`], returning `None` is the result cannot be
/// represented by the underlying data structure.
fn checked_add_signed(&self, duration: Duration) -> Option<Self>;
/// Subtracts the given [`Duration`] from the [`SystemTime`], returning `None` is the result
/// cannot be represented by the underlying data structure.
fn checked_sub_signed(&self, duration: Duration) -> Option<Self>;
/// Returns the amount of time elapsed from another [`SystemTime`] to this one. This will be
/// negative if `earlier` is later than `self.`
///
/// If the duration cannot be stored by [`Duration`], the value will be saturated to
/// [`Duration::MIN`] or [`Duration::MAX`] as appropriate.
///
/// # Example
///
/// ```rust
/// # use std::time::SystemTime;
/// # use time::ext::{NumericalDuration, SystemTimeExt};
/// let epoch = SystemTime::UNIX_EPOCH;
/// let other = epoch + 1.seconds();
/// assert_eq!(other.signed_duration_since(epoch), 1.seconds());
/// assert_eq!(epoch.signed_duration_since(other), (-1).seconds());
/// ```
fn signed_duration_since(&self, earlier: Self) -> Duration;
}
impl SystemTimeExt for SystemTime {
#[inline]
fn checked_add_signed(&self, duration: Duration) -> Option<Self> {
if duration.is_positive() {
self.checked_add(duration.unsigned_abs())
} else if duration.is_negative() {
self.checked_sub(duration.unsigned_abs())
} else {
Some(*self)
}
}
#[inline]
fn checked_sub_signed(&self, duration: Duration) -> Option<Self> {
if duration.is_positive() {
self.checked_sub(duration.unsigned_abs())
} else if duration.is_negative() {
self.checked_add(duration.unsigned_abs())
} else {
Some(*self)
}
}
#[inline]
fn signed_duration_since(&self, earlier: Self) -> Duration {
match self.duration_since(earlier) {
Ok(duration) => duration.try_into().unwrap_or(Duration::MAX),
Err(err) => {
let seconds = match i64::try_from(err.duration().as_secs()) {
Ok(seconds) => -seconds,
Err(_) => return Duration::MIN,
};
let nanoseconds = -err.duration().subsec_nanos().cast_signed();
// Safety: `nanoseconds` is guaranteed to be between -999_999_999 and 0
// inclusive.
unsafe { Duration::new_unchecked(seconds, nanoseconds) }
}
}
}
}