1 use crate::Duration;
2 use core::{
3     cmp::{Ord, Ordering, PartialEq, PartialOrd},
4     ops::{Add, AddAssign, Sub, SubAssign},
5     time::Duration as StdDuration,
6 };
7 use standback::convert::{TryFrom, TryInto};
8 use std::time::Instant as StdInstant;
9 
10 /// A measurement of a monotonically non-decreasing clock. Opaque and useful
11 /// only with [`Duration`].
12 ///
13 /// Instants are always guaranteed to be no less than any previously measured
14 /// instant when created, and are often useful for tasks such as measuring
15 /// benchmarks or timing how long an operation takes.
16 ///
17 /// Note, however, that instants are not guaranteed to be **steady**. In other
18 /// words, each tick of the underlying clock may not be the same length (e.g.
19 /// some seconds may be longer than others). An instant may jump forwards or
20 /// experience time dilation (slow down or speed up), but it will never go
21 /// backwards.
22 ///
23 /// Instants are opaque types that can only be compared to one another. There is
24 /// no method to get "the number of seconds" from an instant. Instead, it only
25 /// allows measuring the duration between two instants (or comparing two
26 /// instants).
27 ///
28 /// This implementation allows for operations with signed [`Duration`]s, but is
29 /// otherwise identical to [`std::time::Instant`].
30 #[cfg_attr(__time_02_docs, doc(cfg(feature = "std")))]
31 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
32 pub struct Instant {
33     /// Inner representation, using `std::time::Instant`.
34     inner: StdInstant,
35 }
36 
37 impl Instant {
38     /// Returns an `Instant` corresponding to "now".
39     ///
40     /// ```rust
41     /// # use time::Instant;
42     /// println!("{:?}", Instant::now());
43     /// ```
now() -> Self44     pub fn now() -> Self {
45         Self {
46             inner: StdInstant::now(),
47         }
48     }
49 
50     /// Returns the amount of time elapsed since this instant was created. The
51     /// duration will always be nonnegative if the instant is not synthetically
52     /// created.
53     ///
54     /// ```rust
55     /// # use time::{Instant, prelude::*};
56     /// # use std::thread;
57     /// let instant = Instant::now();
58     /// thread::sleep(1.std_milliseconds());
59     /// assert!(instant.elapsed() >= 1.milliseconds());
60     /// ```
elapsed(self) -> Duration61     pub fn elapsed(self) -> Duration {
62         Self::now() - self
63     }
64 
65     /// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be
66     /// represented as `Instant` (which means it's inside the bounds of the
67     /// underlying data structure), `None` otherwise.
68     ///
69     /// ```rust
70     /// # use time::{Instant, prelude::*};
71     /// let now = Instant::now();
72     /// assert_eq!(
73     ///     now.checked_add(5.seconds()),
74     ///     Some(now + 5.seconds())
75     /// );
76     /// assert_eq!(
77     ///     now.checked_add((-5).seconds()),
78     ///     Some(now + (-5).seconds())
79     /// );
80     /// ```
81     ///
82     /// This function is only present when using rustc >= 1.34.0.
83     #[cfg(__time_02_instant_checked_ops)]
checked_add(self, duration: Duration) -> Option<Self>84     pub fn checked_add(self, duration: Duration) -> Option<Self> {
85         if duration.is_zero() {
86             Some(self)
87         } else if duration.is_positive() {
88             self.inner.checked_add(duration.abs_std()).map(From::from)
89         } else {
90             // duration.is_negative()
91             self.inner.checked_sub(duration.abs_std()).map(From::from)
92         }
93     }
94 
95     /// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be
96     /// represented as `Instant` (which means it's inside the bounds of the
97     /// underlying data structure), `None` otherwise.
98     ///
99     /// ```rust
100     /// # use time::{Instant, prelude::*};
101     /// let now = Instant::now();
102     /// assert_eq!(
103     ///     now.checked_sub(5.seconds()),
104     ///     Some(now - 5.seconds())
105     /// );
106     /// assert_eq!(
107     ///     now.checked_sub((-5).seconds()),
108     ///     Some(now - (-5).seconds())
109     /// );
110     /// ```
111     ///
112     /// This function is only present when using rustc >= 1.34.0.
113     #[cfg(__time_02_instant_checked_ops)]
checked_sub(self, duration: Duration) -> Option<Self>114     pub fn checked_sub(self, duration: Duration) -> Option<Self> {
115         self.checked_add(-duration)
116     }
117 }
118 
119 #[allow(clippy::missing_docs_in_private_items)]
120 impl Instant {
121     #[cfg(feature = "deprecated")]
122     #[deprecated(since = "0.2.0", note = "Use `rhs - lhs`")]
to(&self, later: Self) -> Duration123     pub fn to(&self, later: Self) -> Duration {
124         later - *self
125     }
126 }
127 
128 impl From<StdInstant> for Instant {
from(instant: StdInstant) -> Self129     fn from(instant: StdInstant) -> Self {
130         Self { inner: instant }
131     }
132 }
133 
134 impl From<Instant> for StdInstant {
from(instant: Instant) -> Self135     fn from(instant: Instant) -> Self {
136         instant.inner
137     }
138 }
139 
140 impl Sub for Instant {
141     type Output = Duration;
142 
sub(self, other: Self) -> Self::Output143     fn sub(self, other: Self) -> Self::Output {
144         match self.inner.cmp(&other.inner) {
145             Ordering::Equal => Duration::zero(),
146             Ordering::Greater => (self.inner - other.inner)
147                 .try_into()
148                 .expect("overflow converting `std::time::Duration` to `time::Duration`"),
149             Ordering::Less => -Duration::try_from(other.inner - self.inner)
150                 .expect("overflow converting `std::time::Duration` to `time::Duration`"),
151         }
152     }
153 }
154 
155 impl Sub<StdInstant> for Instant {
156     type Output = Duration;
157 
sub(self, other: StdInstant) -> Self::Output158     fn sub(self, other: StdInstant) -> Self::Output {
159         self - Self::from(other)
160     }
161 }
162 
163 impl Sub<Instant> for StdInstant {
164     type Output = Duration;
165 
sub(self, other: Instant) -> Self::Output166     fn sub(self, other: Instant) -> Self::Output {
167         Instant::from(self) - other
168     }
169 }
170 
171 impl Add<Duration> for Instant {
172     type Output = Self;
173 
add(self, duration: Duration) -> Self::Output174     fn add(self, duration: Duration) -> Self::Output {
175         if duration.is_positive() {
176             (self.inner + duration.abs_std()).into()
177         } else if duration.is_negative() {
178             (self.inner - duration.abs_std()).into()
179         } else {
180             self
181         }
182     }
183 }
184 
185 impl Add<Duration> for StdInstant {
186     type Output = Self;
187 
add(self, duration: Duration) -> Self::Output188     fn add(self, duration: Duration) -> Self::Output {
189         (Instant::from(self) + duration).into()
190     }
191 }
192 
193 impl Add<StdDuration> for Instant {
194     type Output = Self;
195 
add(self, duration: StdDuration) -> Self::Output196     fn add(self, duration: StdDuration) -> Self::Output {
197         Self {
198             inner: self.inner + duration,
199         }
200     }
201 }
202 
203 impl AddAssign<Duration> for Instant {
add_assign(&mut self, duration: Duration)204     fn add_assign(&mut self, duration: Duration) {
205         *self = *self + duration;
206     }
207 }
208 
209 impl AddAssign<Duration> for StdInstant {
add_assign(&mut self, duration: Duration)210     fn add_assign(&mut self, duration: Duration) {
211         *self = *self + duration;
212     }
213 }
214 
215 impl AddAssign<StdDuration> for Instant {
add_assign(&mut self, duration: StdDuration)216     fn add_assign(&mut self, duration: StdDuration) {
217         *self = *self + duration;
218     }
219 }
220 
221 impl Sub<Duration> for Instant {
222     type Output = Self;
223 
sub(self, duration: Duration) -> Self::Output224     fn sub(self, duration: Duration) -> Self::Output {
225         self + -duration
226     }
227 }
228 
229 impl Sub<Duration> for StdInstant {
230     type Output = Self;
231 
sub(self, duration: Duration) -> Self::Output232     fn sub(self, duration: Duration) -> Self::Output {
233         (Instant::from(self) - duration).into()
234     }
235 }
236 
237 impl Sub<StdDuration> for Instant {
238     type Output = Self;
239 
sub(self, duration: StdDuration) -> Self::Output240     fn sub(self, duration: StdDuration) -> Self::Output {
241         Self {
242             inner: self.inner - duration,
243         }
244     }
245 }
246 
247 impl SubAssign<Duration> for Instant {
sub_assign(&mut self, duration: Duration)248     fn sub_assign(&mut self, duration: Duration) {
249         *self = *self - duration;
250     }
251 }
252 
253 impl SubAssign<Duration> for StdInstant {
sub_assign(&mut self, duration: Duration)254     fn sub_assign(&mut self, duration: Duration) {
255         *self = *self - duration;
256     }
257 }
258 
259 impl SubAssign<StdDuration> for Instant {
sub_assign(&mut self, duration: StdDuration)260     fn sub_assign(&mut self, duration: StdDuration) {
261         *self = *self - duration;
262     }
263 }
264 
265 impl PartialEq<StdInstant> for Instant {
eq(&self, rhs: &StdInstant) -> bool266     fn eq(&self, rhs: &StdInstant) -> bool {
267         self.inner.eq(rhs)
268     }
269 }
270 
271 impl PartialEq<Instant> for StdInstant {
eq(&self, rhs: &Instant) -> bool272     fn eq(&self, rhs: &Instant) -> bool {
273         self.eq(&rhs.inner)
274     }
275 }
276 
277 impl PartialOrd<StdInstant> for Instant {
partial_cmp(&self, rhs: &StdInstant) -> Option<Ordering>278     fn partial_cmp(&self, rhs: &StdInstant) -> Option<Ordering> {
279         self.inner.partial_cmp(rhs)
280     }
281 }
282 
283 impl PartialOrd<Instant> for StdInstant {
partial_cmp(&self, rhs: &Instant) -> Option<Ordering>284     fn partial_cmp(&self, rhs: &Instant) -> Option<Ordering> {
285         self.partial_cmp(&rhs.inner)
286     }
287 }
288