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#[deprecated(since = "0.3.35", note = "import `time::ext::InstantExt` instead")]
32#[repr(transparent)]
33#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
34pub struct Instant(pub StdInstant);
35
36impl Instant {
37    // region: delegation
38    /// Returns an `Instant` corresponding to "now".
39    ///
40    /// ```rust
41    /// # #![allow(deprecated)]
42    /// # use time::Instant;
43    /// println!("{:?}", Instant::now());
44    /// ```
45    pub fn now() -> Self {
46        Self(StdInstant::now())
47    }
48
49    /// Returns the amount of time elapsed since this instant was created. The duration will always
50    /// be nonnegative if the instant is not synthetically created.
51    ///
52    /// ```rust
53    /// # #![allow(deprecated)]
54    /// # use time::{Instant, ext::{NumericalStdDuration, NumericalDuration}};
55    /// # use std::thread;
56    /// let instant = Instant::now();
57    /// thread::sleep(1.std_milliseconds());
58    /// assert!(instant.elapsed() >= 1.milliseconds());
59    /// ```
60    pub fn elapsed(self) -> Duration {
61        Self::now() - self
62    }
63    // endregion delegation
64
65    // region: checked arithmetic
66    /// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
67    /// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
68    /// otherwise.
69    ///
70    /// ```rust
71    /// # #![allow(deprecated)]
72    /// # use time::{Instant, ext::NumericalDuration};
73    /// let now = Instant::now();
74    /// assert_eq!(now.checked_add(5.seconds()), Some(now + 5.seconds()));
75    /// assert_eq!(now.checked_add((-5).seconds()), Some(now + (-5).seconds()));
76    /// ```
77    pub fn checked_add(self, duration: Duration) -> Option<Self> {
78        if duration.is_zero() {
79            Some(self)
80        } else if duration.is_positive() {
81            self.0.checked_add(duration.unsigned_abs()).map(Self)
82        } else {
83            debug_assert!(duration.is_negative());
84            self.0.checked_sub(duration.unsigned_abs()).map(Self)
85        }
86    }
87
88    /// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
89    /// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
90    /// otherwise.
91    ///
92    /// ```rust
93    /// # #![allow(deprecated)]
94    /// # use time::{Instant, ext::NumericalDuration};
95    /// let now = Instant::now();
96    /// assert_eq!(now.checked_sub(5.seconds()), Some(now - 5.seconds()));
97    /// assert_eq!(now.checked_sub((-5).seconds()), Some(now - (-5).seconds()));
98    /// ```
99    pub fn checked_sub(self, duration: Duration) -> Option<Self> {
100        if duration.is_zero() {
101            Some(self)
102        } else if duration.is_positive() {
103            self.0.checked_sub(duration.unsigned_abs()).map(Self)
104        } else {
105            debug_assert!(duration.is_negative());
106            self.0.checked_add(duration.unsigned_abs()).map(Self)
107        }
108    }
109    // endregion checked arithmetic
110
111    /// Obtain the inner [`std::time::Instant`].
112    ///
113    /// ```rust
114    /// # #![allow(deprecated)]
115    /// # use time::Instant;
116    /// let now = Instant::now();
117    /// assert_eq!(now.into_inner(), now.0);
118    /// ```
119    pub const fn into_inner(self) -> StdInstant {
120        self.0
121    }
122}
123
124// region: trait impls
125impl From<StdInstant> for Instant {
126    fn from(instant: StdInstant) -> Self {
127        Self(instant)
128    }
129}
130
131impl From<Instant> for StdInstant {
132    fn from(instant: Instant) -> Self {
133        instant.0
134    }
135}
136
137impl Sub for Instant {
138    type Output = Duration;
139
140    /// # Panics
141    ///
142    /// This may panic if an overflow occurs.
143    fn sub(self, other: Self) -> Self::Output {
144        match self.0.cmp(&other.0) {
145            Ordering::Equal => Duration::ZERO,
146            Ordering::Greater => (self.0 - other.0)
147                .try_into()
148                .expect("overflow converting `std::time::Duration` to `time::Duration`"),
149            Ordering::Less => -Duration::try_from(other.0 - self.0)
150                .expect("overflow converting `std::time::Duration` to `time::Duration`"),
151        }
152    }
153}
154
155impl Sub<StdInstant> for Instant {
156    type Output = Duration;
157
158    fn sub(self, other: StdInstant) -> Self::Output {
159        self - Self(other)
160    }
161}
162
163impl Sub<Instant> for StdInstant {
164    type Output = Duration;
165
166    fn sub(self, other: Instant) -> Self::Output {
167        Instant(self) - other
168    }
169}
170
171impl Add<Duration> for Instant {
172    type Output = Self;
173
174    /// # Panics
175    ///
176    /// This function may panic if the resulting point in time cannot be represented by the
177    /// underlying data structure.
178    fn add(self, duration: Duration) -> Self::Output {
179        if duration.is_positive() {
180            Self(self.0 + duration.unsigned_abs())
181        } else if duration.is_negative() {
182            #[allow(clippy::unchecked_duration_subtraction)]
183            Self(self.0 - duration.unsigned_abs())
184        } else {
185            debug_assert!(duration.is_zero());
186            self
187        }
188    }
189}
190
191impl Add<Duration> for StdInstant {
192    type Output = Self;
193
194    fn add(self, duration: Duration) -> Self::Output {
195        (Instant(self) + duration).0
196    }
197}
198
199impl Add<StdDuration> for Instant {
200    type Output = Self;
201
202    fn add(self, duration: StdDuration) -> Self::Output {
203        Self(self.0 + duration)
204    }
205}
206
207impl_add_assign!(Instant: Duration, StdDuration);
208impl_add_assign!(StdInstant: Duration);
209
210impl Sub<Duration> for Instant {
211    type Output = Self;
212
213    /// # Panics
214    ///
215    /// This function may panic if the resulting point in time cannot be represented by the
216    /// underlying data structure.
217    fn sub(self, duration: Duration) -> Self::Output {
218        if duration.is_positive() {
219            #[allow(clippy::unchecked_duration_subtraction)]
220            Self(self.0 - duration.unsigned_abs())
221        } else if duration.is_negative() {
222            Self(self.0 + duration.unsigned_abs())
223        } else {
224            debug_assert!(duration.is_zero());
225            self
226        }
227    }
228}
229
230impl Sub<Duration> for StdInstant {
231    type Output = Self;
232
233    fn sub(self, duration: Duration) -> Self::Output {
234        (Instant(self) - duration).0
235    }
236}
237
238impl Sub<StdDuration> for Instant {
239    type Output = Self;
240
241    /// # Panics
242    ///
243    /// This function may panic if the resulting point in time cannot be represented by the
244    /// underlying data structure.
245    fn sub(self, duration: StdDuration) -> Self::Output {
246        #[allow(clippy::unchecked_duration_subtraction)]
247        Self(self.0 - duration)
248    }
249}
250
251impl_sub_assign!(Instant: Duration, StdDuration);
252impl_sub_assign!(StdInstant: Duration);
253
254impl PartialEq<StdInstant> for Instant {
255    fn eq(&self, rhs: &StdInstant) -> bool {
256        self.0.eq(rhs)
257    }
258}
259
260impl PartialEq<Instant> for StdInstant {
261    fn eq(&self, rhs: &Instant) -> bool {
262        self.eq(&rhs.0)
263    }
264}
265
266impl PartialOrd<StdInstant> for Instant {
267    fn partial_cmp(&self, rhs: &StdInstant) -> Option<Ordering> {
268        self.0.partial_cmp(rhs)
269    }
270}
271
272impl PartialOrd<Instant> for StdInstant {
273    fn partial_cmp(&self, rhs: &Instant) -> Option<Ordering> {
274        self.partial_cmp(&rhs.0)
275    }
276}
277
278impl AsRef<StdInstant> for Instant {
279    fn as_ref(&self) -> &StdInstant {
280        &self.0
281    }
282}
283
284impl Borrow<StdInstant> for Instant {
285    fn borrow(&self) -> &StdInstant {
286        &self.0
287    }
288}
289// endregion trait impls