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::SignedDuration;
12
13/// A measurement of a monotonically non-decreasing clock. Opaque and useful only with
14/// [`SignedDuration`].
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 [`SignedDuration`]s, but is otherwise
30/// identical 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) -> SignedDuration {
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: SignedDuration) -> 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: SignedDuration) -> 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 = SignedDuration;
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 => SignedDuration::ZERO,
153 Ordering::Greater => (self.0 - other.0)
154 .try_into()
155 .expect("overflow converting `std::time::Duration` to `time::SignedDuration`"),
156 Ordering::Less => -SignedDuration::try_from(other.0 - self.0)
157 .expect("overflow converting `std::time::Duration` to `time::SignedDuration`"),
158 }
159 }
160}
161
162impl Sub<StdInstant> for Instant {
163 type Output = SignedDuration;
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 = SignedDuration;
173
174 #[inline]
175 fn sub(self, other: Instant) -> Self::Output {
176 Instant(self) - other
177 }
178}
179
180impl Add<SignedDuration> 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: SignedDuration) -> Self::Output {
189 if duration.is_positive() {
190 Self(self.0 + duration.unsigned_abs())
191 } else if duration.is_negative() {
192 #[expect(clippy::unchecked_time_subtraction)]
193 Self(self.0 - duration.unsigned_abs())
194 } else {
195 debug_assert!(duration.is_zero());
196 self
197 }
198 }
199}
200
201impl Add<SignedDuration> for StdInstant {
202 type Output = Self;
203
204 /// # Panics
205 ///
206 /// This function may panic if the resulting point in time cannot be represented by the
207 /// underlying data structure.
208 #[inline]
209 fn add(self, duration: SignedDuration) -> Self::Output {
210 (Instant(self) + duration).0
211 }
212}
213
214impl Add<StdDuration> 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 #[inline]
222 fn add(self, duration: StdDuration) -> Self::Output {
223 Self(self.0 + duration)
224 }
225}
226
227impl AddAssign<SignedDuration> for Instant {
228 /// # Panics
229 ///
230 /// This function may panic if the resulting point in time cannot be represented by the
231 /// underlying data structure.
232 #[inline]
233 fn add_assign(&mut self, rhs: SignedDuration) {
234 *self = *self + rhs;
235 }
236}
237
238impl AddAssign<StdDuration> for Instant {
239 /// # Panics
240 ///
241 /// This function may panic if the resulting point in time cannot be represented by the
242 /// underlying data structure.
243 #[inline]
244 fn add_assign(&mut self, rhs: StdDuration) {
245 *self = *self + rhs;
246 }
247}
248
249impl AddAssign<SignedDuration> for StdInstant {
250 /// # Panics
251 ///
252 /// This function may panic if the resulting point in time cannot be represented by the
253 /// underlying data structure.
254 #[inline]
255 fn add_assign(&mut self, rhs: SignedDuration) {
256 *self = *self + rhs;
257 }
258}
259
260impl Sub<SignedDuration> for Instant {
261 type Output = Self;
262
263 /// # Panics
264 ///
265 /// This function may panic if the resulting point in time cannot be represented by the
266 /// underlying data structure.
267 #[inline]
268 fn sub(self, duration: SignedDuration) -> Self::Output {
269 if duration.is_positive() {
270 #[expect(clippy::unchecked_time_subtraction)]
271 Self(self.0 - duration.unsigned_abs())
272 } else if duration.is_negative() {
273 Self(self.0 + duration.unsigned_abs())
274 } else {
275 debug_assert!(duration.is_zero());
276 self
277 }
278 }
279}
280
281impl Sub<SignedDuration> for StdInstant {
282 type Output = Self;
283
284 /// # Panics
285 ///
286 /// This function may panic if the resulting point in time cannot be represented by the
287 /// underlying data structure.
288 #[inline]
289 fn sub(self, duration: SignedDuration) -> Self::Output {
290 (Instant(self) - duration).0
291 }
292}
293
294impl Sub<StdDuration> for Instant {
295 type Output = Self;
296
297 /// # Panics
298 ///
299 /// This function may panic if the resulting point in time cannot be represented by the
300 /// underlying data structure.
301 #[inline]
302 fn sub(self, duration: StdDuration) -> Self::Output {
303 #[expect(clippy::unchecked_time_subtraction)]
304 Self(self.0 - duration)
305 }
306}
307
308impl SubAssign<SignedDuration> for Instant {
309 /// # Panics
310 ///
311 /// This function may panic if the resulting point in time cannot be represented by the
312 /// underlying data structure.
313 #[inline]
314 fn sub_assign(&mut self, rhs: SignedDuration) {
315 *self = *self - rhs;
316 }
317}
318
319impl SubAssign<StdDuration> for Instant {
320 /// # Panics
321 ///
322 /// This function may panic if the resulting point in time cannot be represented by the
323 /// underlying data structure.
324 #[inline]
325 fn sub_assign(&mut self, rhs: StdDuration) {
326 *self = *self - rhs;
327 }
328}
329
330impl SubAssign<SignedDuration> for StdInstant {
331 /// # Panics
332 ///
333 /// This function may panic if the resulting point in time cannot be represented by the
334 /// underlying data structure.
335 #[inline]
336 fn sub_assign(&mut self, rhs: SignedDuration) {
337 *self = *self - rhs;
338 }
339}
340
341impl PartialEq<StdInstant> for Instant {
342 #[inline]
343 fn eq(&self, rhs: &StdInstant) -> bool {
344 self.0.eq(rhs)
345 }
346}
347
348impl PartialEq<Instant> for StdInstant {
349 #[inline]
350 fn eq(&self, rhs: &Instant) -> bool {
351 self.eq(&rhs.0)
352 }
353}
354
355impl PartialOrd<StdInstant> for Instant {
356 #[inline]
357 fn partial_cmp(&self, rhs: &StdInstant) -> Option<Ordering> {
358 self.0.partial_cmp(rhs)
359 }
360}
361
362impl PartialOrd<Instant> for StdInstant {
363 #[inline]
364 fn partial_cmp(&self, rhs: &Instant) -> Option<Ordering> {
365 self.partial_cmp(&rhs.0)
366 }
367}
368
369impl AsRef<StdInstant> for Instant {
370 #[inline]
371 fn as_ref(&self) -> &StdInstant {
372 &self.0
373 }
374}
375
376impl Borrow<StdInstant> for Instant {
377 #[inline]
378 fn borrow(&self) -> &StdInstant {
379 &self.0
380 }
381}