time/
instant.rs

1//! The [`Instant`] struct and its associated `impl`s.
2
3#![allow(deprecated)]
4
5use core::borrow::Borrow;
6use core::cmp::{Ord, Ordering, PartialEq, PartialOrd};
7use core::ops::{Add, Sub};
8use core::time::Duration as StdDuration;
9use std::time::Instant as StdInstant;
10
11use crate::internal_macros::{impl_add_assign, impl_sub_assign};
12use crate::Duration;
13
14/// A measurement of a monotonically non-decreasing clock. Opaque and useful only with [`Duration`].
15///
16/// Instants are always guaranteed to be no less than any previously measured instant when created,
17/// and are often useful for tasks such as measuring benchmarks or timing how long an operation
18/// takes.
19///
20/// Note, however, that instants are not guaranteed to be **steady**. In other words, each tick of
21/// the underlying clock may not be the same length (e.g. some seconds may be longer than others).
22/// An instant may jump forwards or experience time dilation (slow down or speed up), but it will
23/// never go backwards.
24///
25/// Instants are opaque types that can only be compared to one another. There is no method to get
26/// "the number of seconds" from an instant. Instead, it only allows measuring the duration between
27/// two instants (or comparing two instants).
28///
29/// This implementation allows for operations with signed [`Duration`]s, but is otherwise identical
30/// to [`std::time::Instant`].
31#[doc(hidden)]
32#[deprecated(
33    since = "0.3.35",
34    note = "import `std::time::Instant` and `time::ext::InstantExt` instead"
35)]
36#[repr(transparent)]
37#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
38pub struct Instant(pub StdInstant);
39
40impl Instant {
41    // region: delegation
42    /// Returns an `Instant` corresponding to "now".
43    ///
44    /// ```rust
45    /// # #![allow(deprecated)]
46    /// # use time::Instant;
47    /// println!("{:?}", Instant::now());
48    /// ```
49    pub fn now() -> Self {
50        Self(StdInstant::now())
51    }
52
53    /// Returns the amount of time elapsed since this instant was created. The duration will always
54    /// be nonnegative if the instant is not synthetically created.
55    ///
56    /// ```rust
57    /// # #![allow(deprecated)]
58    /// # use time::{Instant, ext::{NumericalStdDuration, NumericalDuration}};
59    /// # use std::thread;
60    /// let instant = Instant::now();
61    /// thread::sleep(1.std_milliseconds());
62    /// assert!(instant.elapsed() >= 1.milliseconds());
63    /// ```
64    pub fn elapsed(self) -> Duration {
65        Self::now() - self
66    }
67    // endregion delegation
68
69    // region: checked arithmetic
70    /// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
71    /// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
72    /// otherwise.
73    ///
74    /// ```rust
75    /// # #![allow(deprecated)]
76    /// # use time::{Instant, ext::NumericalDuration};
77    /// let now = Instant::now();
78    /// assert_eq!(now.checked_add(5.seconds()), Some(now + 5.seconds()));
79    /// assert_eq!(now.checked_add((-5).seconds()), Some(now + (-5).seconds()));
80    /// ```
81    pub fn checked_add(self, duration: Duration) -> Option<Self> {
82        if duration.is_zero() {
83            Some(self)
84        } else if duration.is_positive() {
85            self.0.checked_add(duration.unsigned_abs()).map(Self)
86        } else {
87            debug_assert!(duration.is_negative());
88            self.0.checked_sub(duration.unsigned_abs()).map(Self)
89        }
90    }
91
92    /// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
93    /// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
94    /// otherwise.
95    ///
96    /// ```rust
97    /// # #![allow(deprecated)]
98    /// # use time::{Instant, ext::NumericalDuration};
99    /// let now = Instant::now();
100    /// assert_eq!(now.checked_sub(5.seconds()), Some(now - 5.seconds()));
101    /// assert_eq!(now.checked_sub((-5).seconds()), Some(now - (-5).seconds()));
102    /// ```
103    pub fn checked_sub(self, duration: Duration) -> Option<Self> {
104        if duration.is_zero() {
105            Some(self)
106        } else if duration.is_positive() {
107            self.0.checked_sub(duration.unsigned_abs()).map(Self)
108        } else {
109            debug_assert!(duration.is_negative());
110            self.0.checked_add(duration.unsigned_abs()).map(Self)
111        }
112    }
113    // endregion checked arithmetic
114
115    /// Obtain the inner [`std::time::Instant`].
116    ///
117    /// ```rust
118    /// # #![allow(deprecated)]
119    /// # use time::Instant;
120    /// let now = Instant::now();
121    /// assert_eq!(now.into_inner(), now.0);
122    /// ```
123    pub const fn into_inner(self) -> StdInstant {
124        self.0
125    }
126}
127
128// region: trait impls
129impl From<StdInstant> for Instant {
130    fn from(instant: StdInstant) -> Self {
131        Self(instant)
132    }
133}
134
135impl From<Instant> for StdInstant {
136    fn from(instant: Instant) -> Self {
137        instant.0
138    }
139}
140
141impl Sub for Instant {
142    type Output = Duration;
143
144    /// # Panics
145    ///
146    /// This may panic if an overflow occurs.
147    fn sub(self, other: Self) -> Self::Output {
148        match self.0.cmp(&other.0) {
149            Ordering::Equal => Duration::ZERO,
150            Ordering::Greater => (self.0 - other.0)
151                .try_into()
152                .expect("overflow converting `std::time::Duration` to `time::Duration`"),
153            Ordering::Less => -Duration::try_from(other.0 - self.0)
154                .expect("overflow converting `std::time::Duration` to `time::Duration`"),
155        }
156    }
157}
158
159impl Sub<StdInstant> for Instant {
160    type Output = Duration;
161
162    fn sub(self, other: StdInstant) -> Self::Output {
163        self - Self(other)
164    }
165}
166
167impl Sub<Instant> for StdInstant {
168    type Output = Duration;
169
170    fn sub(self, other: Instant) -> Self::Output {
171        Instant(self) - other
172    }
173}
174
175impl Add<Duration> for Instant {
176    type Output = Self;
177
178    /// # Panics
179    ///
180    /// This function may panic if the resulting point in time cannot be represented by the
181    /// underlying data structure.
182    fn add(self, duration: Duration) -> Self::Output {
183        if duration.is_positive() {
184            Self(self.0 + duration.unsigned_abs())
185        } else if duration.is_negative() {
186            #[allow(clippy::unchecked_duration_subtraction)]
187            Self(self.0 - duration.unsigned_abs())
188        } else {
189            debug_assert!(duration.is_zero());
190            self
191        }
192    }
193}
194
195impl Add<Duration> for StdInstant {
196    type Output = Self;
197
198    fn add(self, duration: Duration) -> Self::Output {
199        (Instant(self) + duration).0
200    }
201}
202
203impl Add<StdDuration> for Instant {
204    type Output = Self;
205
206    fn add(self, duration: StdDuration) -> Self::Output {
207        Self(self.0 + duration)
208    }
209}
210
211impl_add_assign!(Instant: Duration, StdDuration);
212impl_add_assign!(StdInstant: Duration);
213
214impl Sub<Duration> for Instant {
215    type Output = Self;
216
217    /// # Panics
218    ///
219    /// This function may panic if the resulting point in time cannot be represented by the
220    /// underlying data structure.
221    fn sub(self, duration: Duration) -> Self::Output {
222        if duration.is_positive() {
223            #[allow(clippy::unchecked_duration_subtraction)]
224            Self(self.0 - duration.unsigned_abs())
225        } else if duration.is_negative() {
226            Self(self.0 + duration.unsigned_abs())
227        } else {
228            debug_assert!(duration.is_zero());
229            self
230        }
231    }
232}
233
234impl Sub<Duration> for StdInstant {
235    type Output = Self;
236
237    fn sub(self, duration: Duration) -> Self::Output {
238        (Instant(self) - duration).0
239    }
240}
241
242impl Sub<StdDuration> for Instant {
243    type Output = Self;
244
245    /// # Panics
246    ///
247    /// This function may panic if the resulting point in time cannot be represented by the
248    /// underlying data structure.
249    fn sub(self, duration: StdDuration) -> Self::Output {
250        #[allow(clippy::unchecked_duration_subtraction)]
251        Self(self.0 - duration)
252    }
253}
254
255impl_sub_assign!(Instant: Duration, StdDuration);
256impl_sub_assign!(StdInstant: Duration);
257
258impl PartialEq<StdInstant> for Instant {
259    fn eq(&self, rhs: &StdInstant) -> bool {
260        self.0.eq(rhs)
261    }
262}
263
264impl PartialEq<Instant> for StdInstant {
265    fn eq(&self, rhs: &Instant) -> bool {
266        self.eq(&rhs.0)
267    }
268}
269
270impl PartialOrd<StdInstant> for Instant {
271    fn partial_cmp(&self, rhs: &StdInstant) -> Option<Ordering> {
272        self.0.partial_cmp(rhs)
273    }
274}
275
276impl PartialOrd<Instant> for StdInstant {
277    fn partial_cmp(&self, rhs: &Instant) -> Option<Ordering> {
278        self.partial_cmp(&rhs.0)
279    }
280}
281
282impl AsRef<StdInstant> for Instant {
283    fn as_ref(&self) -> &StdInstant {
284        &self.0
285    }
286}
287
288impl Borrow<StdInstant> for Instant {
289    fn borrow(&self) -> &StdInstant {
290        &self.0
291    }
292}
293// endregion trait impls