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