Coverage Report

Created: 2025-09-05 06:11

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