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, 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    /// Returns an `Instant` corresponding to "now".
42    ///
43    /// ```rust
44    /// # #![expect(deprecated)]
45    /// # use time::Instant;
46    /// println!("{:?}", Instant::now());
47    /// ```
48    #[inline]
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    /// # #![expect(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    #[inline]
65    pub fn elapsed(self) -> Duration {
66        Self::now() - self
67    }
68
69    /// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
70    /// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
71    /// otherwise.
72    ///
73    /// ```rust
74    /// # #![expect(deprecated)]
75    /// # use time::{Instant, ext::NumericalDuration};
76    /// let now = Instant::now();
77    /// assert_eq!(now.checked_add(5.seconds()), Some(now + 5.seconds()));
78    /// assert_eq!(now.checked_add((-5).seconds()), Some(now + (-5).seconds()));
79    /// ```
80    #[inline]
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    /// # #![expect(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    #[inline]
104    pub fn checked_sub(self, duration: Duration) -> Option<Self> {
105        if duration.is_zero() {
106            Some(self)
107        } else if duration.is_positive() {
108            self.0.checked_sub(duration.unsigned_abs()).map(Self)
109        } else {
110            debug_assert!(duration.is_negative());
111            self.0.checked_add(duration.unsigned_abs()).map(Self)
112        }
113    }
114
115    /// Obtain the inner [`std::time::Instant`].
116    ///
117    /// ```rust
118    /// # #![expect(deprecated)]
119    /// # use time::Instant;
120    /// let now = Instant::now();
121    /// assert_eq!(now.into_inner(), now.0);
122    /// ```
123    #[inline]
124    pub const fn into_inner(self) -> StdInstant {
125        self.0
126    }
127}
128
129impl From<StdInstant> for Instant {
130    #[inline]
131    fn from(instant: StdInstant) -> Self {
132        Self(instant)
133    }
134}
135
136impl From<Instant> for StdInstant {
137    #[inline]
138    fn from(instant: Instant) -> Self {
139        instant.0
140    }
141}
142
143impl Sub for Instant {
144    type Output = Duration;
145
146    /// # Panics
147    ///
148    /// This may panic if an overflow occurs.
149    #[inline]
150    fn sub(self, other: Self) -> Self::Output {
151        match self.0.cmp(&other.0) {
152            Ordering::Equal => Duration::ZERO,
153            Ordering::Greater => (self.0 - other.0)
154                .try_into()
155                .expect("overflow converting `std::time::Duration` to `time::Duration`"),
156            Ordering::Less => -Duration::try_from(other.0 - self.0)
157                .expect("overflow converting `std::time::Duration` to `time::Duration`"),
158        }
159    }
160}
161
162impl Sub<StdInstant> for Instant {
163    type Output = Duration;
164
165    #[inline]
166    fn sub(self, other: StdInstant) -> Self::Output {
167        self - Self(other)
168    }
169}
170
171impl Sub<Instant> for StdInstant {
172    type Output = Duration;
173
174    #[inline]
175    fn sub(self, other: Instant) -> Self::Output {
176        Instant(self) - other
177    }
178}
179
180impl Add<Duration> for Instant {
181    type Output = Self;
182
183    /// # Panics
184    ///
185    /// This function may panic if the resulting point in time cannot be represented by the
186    /// underlying data structure.
187    #[inline]
188    fn add(self, duration: Duration) -> Self::Output {
189        if duration.is_positive() {
190            Self(self.0 + duration.unsigned_abs())
191        } else if duration.is_negative() {
192            #[expect(clippy::unchecked_duration_subtraction)]
193            Self(self.0 - duration.unsigned_abs())
194        } else {
195            debug_assert!(duration.is_zero());
196            self
197        }
198    }
199}
200
201impl Add<Duration> for StdInstant {
202    type Output = Self;
203
204    #[inline]
205    fn add(self, duration: Duration) -> Self::Output {
206        (Instant(self) + duration).0
207    }
208}
209
210impl Add<StdDuration> for Instant {
211    type Output = Self;
212
213    #[inline]
214    fn add(self, duration: StdDuration) -> Self::Output {
215        Self(self.0 + duration)
216    }
217}
218
219impl_add_assign!(Instant: Duration, StdDuration);
220impl_add_assign!(StdInstant: Duration);
221
222impl Sub<Duration> for Instant {
223    type Output = Self;
224
225    /// # Panics
226    ///
227    /// This function may panic if the resulting point in time cannot be represented by the
228    /// underlying data structure.
229    #[inline]
230    fn sub(self, duration: Duration) -> Self::Output {
231        if duration.is_positive() {
232            #[expect(clippy::unchecked_duration_subtraction)]
233            Self(self.0 - duration.unsigned_abs())
234        } else if duration.is_negative() {
235            Self(self.0 + duration.unsigned_abs())
236        } else {
237            debug_assert!(duration.is_zero());
238            self
239        }
240    }
241}
242
243impl Sub<Duration> for StdInstant {
244    type Output = Self;
245
246    #[inline]
247    fn sub(self, duration: Duration) -> Self::Output {
248        (Instant(self) - duration).0
249    }
250}
251
252impl Sub<StdDuration> for Instant {
253    type Output = Self;
254
255    /// # Panics
256    ///
257    /// This function may panic if the resulting point in time cannot be represented by the
258    /// underlying data structure.
259    #[inline]
260    fn sub(self, duration: StdDuration) -> Self::Output {
261        #[expect(clippy::unchecked_duration_subtraction)]
262        Self(self.0 - duration)
263    }
264}
265
266impl_sub_assign!(Instant: Duration, StdDuration);
267impl_sub_assign!(StdInstant: Duration);
268
269impl PartialEq<StdInstant> for Instant {
270    #[inline]
271    fn eq(&self, rhs: &StdInstant) -> bool {
272        self.0.eq(rhs)
273    }
274}
275
276impl PartialEq<Instant> for StdInstant {
277    #[inline]
278    fn eq(&self, rhs: &Instant) -> bool {
279        self.eq(&rhs.0)
280    }
281}
282
283impl PartialOrd<StdInstant> for Instant {
284    #[inline]
285    fn partial_cmp(&self, rhs: &StdInstant) -> Option<Ordering> {
286        self.0.partial_cmp(rhs)
287    }
288}
289
290impl PartialOrd<Instant> for StdInstant {
291    #[inline]
292    fn partial_cmp(&self, rhs: &Instant) -> Option<Ordering> {
293        self.partial_cmp(&rhs.0)
294    }
295}
296
297impl AsRef<StdInstant> for Instant {
298    #[inline]
299    fn as_ref(&self) -> &StdInstant {
300        &self.0
301    }
302}
303
304impl Borrow<StdInstant> for Instant {
305    #[inline]
306    fn borrow(&self) -> &StdInstant {
307        &self.0
308    }
309}