Coverage Report

Created: 2026-02-14 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/time-0.3.47/src/ext/systemtime.rs
Line
Count
Source
1
use std::time::SystemTime;
2
3
use crate::Duration;
4
5
/// Sealed trait to prevent downstream implementations.
6
mod sealed {
7
    /// A trait that cannot be implemented by downstream users.
8
    pub trait Sealed: Sized {}
9
    impl Sealed for std::time::SystemTime {}
10
}
11
12
/// An extension trait for [`std::time::SystemTime`] that adds methods for
13
/// [`time::Duration`](Duration)s.
14
pub trait SystemTimeExt: sealed::Sealed {
15
    /// Adds the given [`Duration`] to the [`SystemTime`], returning `None` is the result cannot be
16
    /// represented by the underlying data structure.
17
    fn checked_add_signed(&self, duration: Duration) -> Option<Self>;
18
19
    /// Subtracts the given [`Duration`] from the [`SystemTime`], returning `None` is the result
20
    /// cannot be represented by the underlying data structure.
21
    fn checked_sub_signed(&self, duration: Duration) -> Option<Self>;
22
23
    /// Returns the amount of time elapsed from another [`SystemTime`] to this one. This will be
24
    /// negative if `earlier` is later than `self.`
25
    ///
26
    /// If the duration cannot be stored by [`Duration`], the value will be saturated to
27
    /// [`Duration::MIN`] or [`Duration::MAX`] as appropriate.
28
    ///
29
    /// # Example
30
    ///
31
    /// ```rust
32
    /// # use std::time::SystemTime;
33
    /// # use time::ext::{NumericalDuration, SystemTimeExt};
34
    /// let epoch = SystemTime::UNIX_EPOCH;
35
    /// let other = epoch + 1.seconds();
36
    /// assert_eq!(other.signed_duration_since(epoch), 1.seconds());
37
    /// assert_eq!(epoch.signed_duration_since(other), (-1).seconds());
38
    /// ```
39
    fn signed_duration_since(&self, earlier: Self) -> Duration;
40
}
41
42
impl SystemTimeExt for SystemTime {
43
    #[inline]
44
0
    fn checked_add_signed(&self, duration: Duration) -> Option<Self> {
45
0
        if duration.is_positive() {
46
0
            self.checked_add(duration.unsigned_abs())
47
0
        } else if duration.is_negative() {
48
0
            self.checked_sub(duration.unsigned_abs())
49
        } else {
50
0
            Some(*self)
51
        }
52
0
    }
53
54
    #[inline]
55
0
    fn checked_sub_signed(&self, duration: Duration) -> Option<Self> {
56
0
        if duration.is_positive() {
57
0
            self.checked_sub(duration.unsigned_abs())
58
0
        } else if duration.is_negative() {
59
0
            self.checked_add(duration.unsigned_abs())
60
        } else {
61
0
            Some(*self)
62
        }
63
0
    }
64
65
    #[inline]
66
0
    fn signed_duration_since(&self, earlier: Self) -> Duration {
67
0
        match self.duration_since(earlier) {
68
0
            Ok(duration) => duration.try_into().unwrap_or(Duration::MAX),
69
0
            Err(err) => {
70
0
                let seconds = match i64::try_from(err.duration().as_secs()) {
71
0
                    Ok(seconds) => -seconds,
72
0
                    Err(_) => return Duration::MIN,
73
                };
74
0
                let nanoseconds = -err.duration().subsec_nanos().cast_signed();
75
76
                // Safety: `nanoseconds` is guaranteed to be between -999_999_999 and 0
77
                // inclusive.
78
0
                unsafe { Duration::new_unchecked(seconds, nanoseconds) }
79
            }
80
        }
81
0
    }
82
}