time/
instant.rs

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