time/duration.rs
1//! The [`Duration`] struct and its associated `impl`s.
2
3use core::cmp::Ordering;
4use core::fmt;
5use core::hash::{Hash, Hasher};
6use core::iter::Sum;
7use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
8use core::time::Duration as StdDuration;
9#[cfg(feature = "std")]
10use std::time::SystemTime;
11
12use deranged::ri32;
13use num_conv::prelude::*;
14
15#[cfg(feature = "std")]
16#[expect(deprecated)]
17use crate::Instant;
18use crate::error;
19use crate::internal_macros::const_try_opt;
20use crate::unit::*;
21
22#[derive(Debug)]
23enum FloatConstructorError {
24 Nan,
25 NegOverflow,
26 PosOverflow,
27}
28
29/// By explicitly inserting this enum where padding is expected, the compiler is able to better
30/// perform niche value optimization.
31#[repr(u32)]
32#[derive(Debug, Clone, Copy)]
33pub(crate) enum Padding {
34 #[allow(clippy::missing_docs_in_private_items)]
35 Optimize,
36}
37
38/// The type of the `nanosecond` field of `Duration`.
39type Nanoseconds =
40 ri32<{ -Nanosecond::per_t::<i32>(Second) + 1 }, { Nanosecond::per_t::<i32>(Second) - 1 }>;
41
42/// A span of time with nanosecond precision.
43///
44/// Each `Duration` is composed of a whole number of seconds and a fractional part represented in
45/// nanoseconds.
46///
47/// This implementation allows for negative durations, unlike [`core::time::Duration`].
48#[repr(C)]
49#[derive(Clone, Copy)]
50pub struct Duration {
51 /// Number of whole seconds.
52 seconds: i64,
53 /// Number of nanoseconds within the second. The sign always matches the `seconds` field.
54 // Sign must match that of `seconds` (though this is not a safety requirement).
55 nanoseconds: Nanoseconds,
56 _padding: Padding,
57}
58
59impl fmt::Debug for Duration {
60 #[inline]
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 f.debug_struct("Duration")
63 .field("seconds", &self.seconds)
64 .field("nanoseconds", &self.nanoseconds)
65 .finish()
66 }
67}
68
69impl PartialEq for Duration {
70 #[inline]
71 fn eq(&self, other: &Self) -> bool {
72 self.as_int_for_equality() == other.as_int_for_equality()
73 }
74}
75
76impl Eq for Duration {}
77
78impl PartialOrd for Duration {
79 #[inline]
80 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
81 Some(self.cmp(other))
82 }
83}
84
85impl Ord for Duration {
86 #[inline]
87 fn cmp(&self, other: &Self) -> Ordering {
88 self.seconds
89 .cmp(&other.seconds)
90 .then_with(|| self.nanoseconds.cmp(&other.nanoseconds))
91 }
92}
93
94impl Hash for Duration {
95 fn hash<H>(&self, state: &mut H)
96 where
97 H: Hasher,
98 {
99 self.as_int_for_equality().hash(state);
100 }
101}
102
103impl Default for Duration {
104 #[inline]
105 fn default() -> Self {
106 Self::ZERO
107 }
108}
109
110/// This is adapted from the [`std` implementation][std], which uses mostly bit
111/// operations to ensure the highest precision:
112///
113/// Changes from `std` are marked and explained below.
114///
115/// [std]: https://github.com/rust-lang/rust/blob/3a37c2f0523c87147b64f1b8099fc9df22e8c53e/library/core/src/time.rs#L1262-L1340
116#[rustfmt::skip] // Skip `rustfmt` because it reformats the arguments of the macro weirdly.
117macro_rules! try_from_secs {
118 (
119 secs = $secs: expr,
120 mantissa_bits = $mant_bits: literal,
121 exponent_bits = $exp_bits: literal,
122 offset = $offset: literal,
123 bits_ty = $bits_ty:ty,
124 bits_ty_signed = $bits_ty_signed:ty,
125 double_ty = $double_ty:ty,
126 float_ty = $float_ty:ty,
127 ) => {{
128 'value: {
129 const MIN_EXP: i16 = 1 - (1i16 << $exp_bits) / 2;
130 const MANT_MASK: $bits_ty = (1 << $mant_bits) - 1;
131 const EXP_MASK: $bits_ty = (1 << $exp_bits) - 1;
132
133 // Change from std: No error check for negative values necessary.
134
135 let bits = $secs.to_bits();
136 let mant = (bits & MANT_MASK) | (MANT_MASK + 1);
137 let exp = ((bits >> $mant_bits) & EXP_MASK) as i16 + MIN_EXP;
138
139 let (secs, nanos) = if exp < -31 {
140 // the input represents less than 1ns and can not be rounded to it
141 (0u64, 0u32)
142 } else if exp < 0 {
143 // the input is less than 1 second
144 let t = (mant as $double_ty) << ($offset + exp);
145 let nanos_offset = $mant_bits + $offset;
146 #[allow(trivial_numeric_casts)]
147 let nanos_tmp = Nanosecond::per_t::<u128>(Second) * t as u128;
148 let nanos = (nanos_tmp >> nanos_offset) as u32;
149
150 let rem_mask = (1 << nanos_offset) - 1;
151 let rem_msb_mask = 1 << (nanos_offset - 1);
152 let rem = nanos_tmp & rem_mask;
153 let is_tie = rem == rem_msb_mask;
154 let is_even = (nanos & 1) == 0;
155 let rem_msb = nanos_tmp & rem_msb_mask == 0;
156 let add_ns = !(rem_msb || (is_even && is_tie));
157
158 // f32 does not have enough precision to trigger the second branch
159 // since it can not represent numbers between 0.999_999_940_395 and 1.0.
160 let nanos = nanos + add_ns as u32;
161 if ($mant_bits == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
162 (0, nanos)
163 } else {
164 (1, 0)
165 }
166 } else if exp < $mant_bits {
167 #[allow(trivial_numeric_casts)]
168 let secs = (mant >> ($mant_bits - exp)) as u64;
169 let t = ((mant << exp) & MANT_MASK) as $double_ty;
170 let nanos_offset = $mant_bits;
171 let nanos_tmp = Nanosecond::per_t::<$double_ty>(Second) * t;
172 let nanos = (nanos_tmp >> nanos_offset) as u32;
173
174 let rem_mask = (1 << nanos_offset) - 1;
175 let rem_msb_mask = 1 << (nanos_offset - 1);
176 let rem = nanos_tmp & rem_mask;
177 let is_tie = rem == rem_msb_mask;
178 let is_even = (nanos & 1) == 0;
179 let rem_msb = nanos_tmp & rem_msb_mask == 0;
180 let add_ns = !(rem_msb || (is_even && is_tie));
181
182 // f32 does not have enough precision to trigger the second branch.
183 // For example, it can not represent numbers between 1.999_999_880...
184 // and 2.0. Bigger values result in even smaller precision of the
185 // fractional part.
186 let nanos = nanos + add_ns as u32;
187 if ($mant_bits == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
188 (secs, nanos)
189 } else {
190 (secs + 1, 0)
191 }
192 } else if exp < 63 {
193 // Change from std: The exponent here is 63 instead of 64,
194 // because i64::MAX + 1 is 2^63.
195
196 // the input has no fractional part
197 #[allow(trivial_numeric_casts)]
198 let secs = (mant as u64) << (exp - $mant_bits);
199 (secs, 0)
200 } else if bits == (i64::MIN as $float_ty).to_bits() {
201 // Change from std: Signed integers are asymmetrical in that
202 // iN::MIN is -iN::MAX - 1. So for example i8 covers the
203 // following numbers -128..=127. The check above (exp < 63)
204 // doesn't cover i64::MIN as that is -2^63, so we have this
205 // additional case to handle the asymmetry of iN::MIN.
206 break 'value Ok(Self::new_ranged_unchecked(i64::MIN, Nanoseconds::new_static::<0>()));
207 } else if $secs.is_nan() {
208 // Change from std: std doesn't differentiate between the error
209 // cases.
210 break 'value Err(FloatConstructorError::Nan);
211 } else if $secs.is_sign_negative() {
212 break 'value Err(FloatConstructorError::NegOverflow);
213 } else {
214 break 'value Err(FloatConstructorError::PosOverflow);
215 };
216
217 // Change from std: All the code is mostly unmodified in that it
218 // simply calculates an unsigned integer. Here we extract the sign
219 // bit and assign it to the number. We basically manually do two's
220 // complement here, we could also use an if and just negate the
221 // numbers based on the sign, but it turns out to be quite a bit
222 // slower.
223 let mask = (bits as $bits_ty_signed) >> ($mant_bits + $exp_bits);
224 #[allow(trivial_numeric_casts)]
225 let secs_signed = ((secs as i64) ^ (mask as i64)) - (mask as i64);
226 #[allow(trivial_numeric_casts)]
227 let nanos_signed = ((nanos as i32) ^ (mask as i32)) - (mask as i32);
228 // Safety: `nanos_signed` is in range.
229 Ok(unsafe { Self::new_unchecked(secs_signed, nanos_signed) })
230 }
231 }};
232}
233
234impl Duration {
235 #[inline]
236 const fn as_int_for_equality(self) -> i128 {
237 // Safety: There are no padding bytes that are not permitted to be read.
238 unsafe { core::mem::transmute(self) }
239 }
240
241 /// Equivalent to `0.seconds()`.
242 ///
243 /// ```rust
244 /// # use time::{Duration, ext::NumericalDuration};
245 /// assert_eq!(Duration::ZERO, 0.seconds());
246 /// ```
247 pub const ZERO: Self = Self::seconds(0);
248
249 /// Equivalent to `1.nanoseconds()`.
250 ///
251 /// ```rust
252 /// # use time::{Duration, ext::NumericalDuration};
253 /// assert_eq!(Duration::NANOSECOND, 1.nanoseconds());
254 /// ```
255 pub const NANOSECOND: Self = Self::nanoseconds(1);
256
257 /// Equivalent to `1.microseconds()`.
258 ///
259 /// ```rust
260 /// # use time::{Duration, ext::NumericalDuration};
261 /// assert_eq!(Duration::MICROSECOND, 1.microseconds());
262 /// ```
263 pub const MICROSECOND: Self = Self::microseconds(1);
264
265 /// Equivalent to `1.milliseconds()`.
266 ///
267 /// ```rust
268 /// # use time::{Duration, ext::NumericalDuration};
269 /// assert_eq!(Duration::MILLISECOND, 1.milliseconds());
270 /// ```
271 pub const MILLISECOND: Self = Self::milliseconds(1);
272
273 /// Equivalent to `1.seconds()`.
274 ///
275 /// ```rust
276 /// # use time::{Duration, ext::NumericalDuration};
277 /// assert_eq!(Duration::SECOND, 1.seconds());
278 /// ```
279 pub const SECOND: Self = Self::seconds(1);
280
281 /// Equivalent to `1.minutes()`.
282 ///
283 /// ```rust
284 /// # use time::{Duration, ext::NumericalDuration};
285 /// assert_eq!(Duration::MINUTE, 1.minutes());
286 /// ```
287 pub const MINUTE: Self = Self::minutes(1);
288
289 /// Equivalent to `1.hours()`.
290 ///
291 /// ```rust
292 /// # use time::{Duration, ext::NumericalDuration};
293 /// assert_eq!(Duration::HOUR, 1.hours());
294 /// ```
295 pub const HOUR: Self = Self::hours(1);
296
297 /// Equivalent to `1.days()`.
298 ///
299 /// ```rust
300 /// # use time::{Duration, ext::NumericalDuration};
301 /// assert_eq!(Duration::DAY, 1.days());
302 /// ```
303 pub const DAY: Self = Self::days(1);
304
305 /// Equivalent to `1.weeks()`.
306 ///
307 /// ```rust
308 /// # use time::{Duration, ext::NumericalDuration};
309 /// assert_eq!(Duration::WEEK, 1.weeks());
310 /// ```
311 pub const WEEK: Self = Self::weeks(1);
312
313 /// The minimum possible duration. Adding any negative duration to this will cause an overflow.
314 pub const MIN: Self = Self::new_ranged(i64::MIN, Nanoseconds::MIN);
315
316 /// The maximum possible duration. Adding any positive duration to this will cause an overflow.
317 pub const MAX: Self = Self::new_ranged(i64::MAX, Nanoseconds::MAX);
318
319 /// Check if a duration is exactly zero.
320 ///
321 /// ```rust
322 /// # use time::ext::NumericalDuration;
323 /// assert!(0.seconds().is_zero());
324 /// assert!(!1.nanoseconds().is_zero());
325 /// ```
326 #[inline]
327 pub const fn is_zero(self) -> bool {
328 self.as_int_for_equality() == Self::ZERO.as_int_for_equality()
329 }
330
331 /// Check if a duration is negative.
332 ///
333 /// ```rust
334 /// # use time::ext::NumericalDuration;
335 /// assert!((-1).seconds().is_negative());
336 /// assert!(!0.seconds().is_negative());
337 /// assert!(!1.seconds().is_negative());
338 /// ```
339 #[inline]
340 pub const fn is_negative(self) -> bool {
341 self.seconds < 0 || self.nanoseconds.get() < 0
342 }
343
344 /// Check if a duration is positive.
345 ///
346 /// ```rust
347 /// # use time::ext::NumericalDuration;
348 /// assert!(1.seconds().is_positive());
349 /// assert!(!0.seconds().is_positive());
350 /// assert!(!(-1).seconds().is_positive());
351 /// ```
352 #[inline]
353 pub const fn is_positive(self) -> bool {
354 self.seconds > 0 || self.nanoseconds.get() > 0
355 }
356
357 /// Get the absolute value of the duration.
358 ///
359 /// This method saturates the returned value if it would otherwise overflow.
360 ///
361 /// ```rust
362 /// # use time::ext::NumericalDuration;
363 /// assert_eq!(1.seconds().abs(), 1.seconds());
364 /// assert_eq!(0.seconds().abs(), 0.seconds());
365 /// assert_eq!((-1).seconds().abs(), 1.seconds());
366 /// ```
367 #[inline]
368 pub const fn abs(self) -> Self {
369 match self.seconds.checked_abs() {
370 Some(seconds) => Self::new_ranged_unchecked(seconds, self.nanoseconds.abs()),
371 None => Self::MAX,
372 }
373 }
374
375 /// Convert the existing `Duration` to a `std::time::Duration` and its sign. This returns a
376 /// [`std::time::Duration`] and does not saturate the returned value (unlike [`Duration::abs`]).
377 ///
378 /// ```rust
379 /// # use time::ext::{NumericalDuration, NumericalStdDuration};
380 /// assert_eq!(1.seconds().unsigned_abs(), 1.std_seconds());
381 /// assert_eq!(0.seconds().unsigned_abs(), 0.std_seconds());
382 /// assert_eq!((-1).seconds().unsigned_abs(), 1.std_seconds());
383 /// ```
384 #[inline]
385 pub const fn unsigned_abs(self) -> StdDuration {
386 StdDuration::new(
387 self.seconds.unsigned_abs(),
388 self.nanoseconds.get().unsigned_abs(),
389 )
390 }
391
392 /// Create a new `Duration` without checking the validity of the components.
393 ///
394 /// # Safety
395 ///
396 /// - `nanoseconds` must be in the range `-999_999_999..=999_999_999`.
397 ///
398 /// While the sign of `nanoseconds` is required to be the same as the sign of `seconds`, this is
399 /// not a safety invariant.
400 #[inline]
401 #[track_caller]
402 pub(crate) const unsafe fn new_unchecked(seconds: i64, nanoseconds: i32) -> Self {
403 Self::new_ranged_unchecked(
404 seconds,
405 // Safety: The caller must uphold the safety invariants.
406 unsafe { Nanoseconds::new_unchecked(nanoseconds) },
407 )
408 }
409
410 /// Create a new `Duration` without checking the validity of the components.
411 #[inline]
412 #[track_caller]
413 pub(crate) const fn new_ranged_unchecked(seconds: i64, nanoseconds: Nanoseconds) -> Self {
414 if seconds < 0 {
415 debug_assert!(nanoseconds.get() <= 0);
416 } else if seconds > 0 {
417 debug_assert!(nanoseconds.get() >= 0);
418 }
419
420 Self {
421 seconds,
422 nanoseconds,
423 _padding: Padding::Optimize,
424 }
425 }
426
427 /// Create a new `Duration` with the provided seconds and nanoseconds. If nanoseconds is at
428 /// least ±10<sup>9</sup>, it will wrap to the number of seconds.
429 ///
430 /// ```rust
431 /// # use time::{Duration, ext::NumericalDuration};
432 /// assert_eq!(Duration::new(1, 0), 1.seconds());
433 /// assert_eq!(Duration::new(-1, 0), (-1).seconds());
434 /// assert_eq!(Duration::new(1, 2_000_000_000), 3.seconds());
435 /// ```
436 ///
437 /// # Panics
438 ///
439 /// This may panic if an overflow occurs.
440 #[inline]
441 #[track_caller]
442 pub const fn new(mut seconds: i64, mut nanoseconds: i32) -> Self {
443 seconds = seconds
444 .checked_add(nanoseconds as i64 / Nanosecond::per_t::<i64>(Second))
445 .expect("overflow constructing `time::Duration`");
446 nanoseconds %= Nanosecond::per_t::<i32>(Second);
447
448 if seconds > 0 && nanoseconds < 0 {
449 // `seconds` cannot overflow here because it is positive.
450 seconds -= 1;
451 nanoseconds += Nanosecond::per_t::<i32>(Second);
452 } else if seconds < 0 && nanoseconds > 0 {
453 // `seconds` cannot overflow here because it is negative.
454 seconds += 1;
455 nanoseconds -= Nanosecond::per_t::<i32>(Second);
456 }
457
458 // Safety: `nanoseconds` is in range due to the modulus above.
459 unsafe { Self::new_unchecked(seconds, nanoseconds) }
460 }
461
462 /// Create a new `Duration` with the provided seconds and nanoseconds.
463 #[inline]
464 pub(crate) const fn new_ranged(mut seconds: i64, mut nanoseconds: Nanoseconds) -> Self {
465 if seconds > 0 && nanoseconds.get() < 0 {
466 // `seconds` cannot overflow here because it is positive.
467 seconds -= 1;
468 // Safety: `nanoseconds` is negative with a maximum of 999,999,999, so adding a billion
469 // to it is guaranteed to result in an in-range value.
470 nanoseconds = unsafe {
471 Nanoseconds::new_unchecked(nanoseconds.get() + Nanosecond::per_t::<i32>(Second))
472 };
473 } else if seconds < 0 && nanoseconds.get() > 0 {
474 // `seconds` cannot overflow here because it is negative.
475 seconds += 1;
476 // Safety: `nanoseconds` is positive with a minimum of -999,999,999, so subtracting a
477 // billion from it is guaranteed to result in an in-range value.
478 nanoseconds = unsafe {
479 Nanoseconds::new_unchecked(nanoseconds.get() - Nanosecond::per_t::<i32>(Second))
480 };
481 }
482
483 Self::new_ranged_unchecked(seconds, nanoseconds)
484 }
485
486 /// Create a new `Duration` with the given number of weeks. Equivalent to
487 /// `Duration::seconds(weeks * 604_800)`.
488 ///
489 /// ```rust
490 /// # use time::{Duration, ext::NumericalDuration};
491 /// assert_eq!(Duration::weeks(1), 604_800.seconds());
492 /// ```
493 ///
494 /// # Panics
495 ///
496 /// This may panic if an overflow occurs.
497 #[inline]
498 #[track_caller]
499 pub const fn weeks(weeks: i64) -> Self {
500 Self::seconds(
501 weeks
502 .checked_mul(Second::per_t(Week))
503 .expect("overflow constructing `time::Duration`"),
504 )
505 }
506
507 /// Create a new `Duration` with the given number of days. Equivalent to
508 /// `Duration::seconds(days * 86_400)`.
509 ///
510 /// ```rust
511 /// # use time::{Duration, ext::NumericalDuration};
512 /// assert_eq!(Duration::days(1), 86_400.seconds());
513 /// ```
514 ///
515 /// # Panics
516 ///
517 /// This may panic if an overflow occurs.
518 #[inline]
519 #[track_caller]
520 pub const fn days(days: i64) -> Self {
521 Self::seconds(
522 days.checked_mul(Second::per_t(Day))
523 .expect("overflow constructing `time::Duration`"),
524 )
525 }
526
527 /// Create a new `Duration` with the given number of hours. Equivalent to
528 /// `Duration::seconds(hours * 3_600)`.
529 ///
530 /// ```rust
531 /// # use time::{Duration, ext::NumericalDuration};
532 /// assert_eq!(Duration::hours(1), 3_600.seconds());
533 /// ```
534 ///
535 /// # Panics
536 ///
537 /// This may panic if an overflow occurs.
538 #[inline]
539 #[track_caller]
540 pub const fn hours(hours: i64) -> Self {
541 Self::seconds(
542 hours
543 .checked_mul(Second::per_t(Hour))
544 .expect("overflow constructing `time::Duration`"),
545 )
546 }
547
548 /// Create a new `Duration` with the given number of minutes. Equivalent to
549 /// `Duration::seconds(minutes * 60)`.
550 ///
551 /// ```rust
552 /// # use time::{Duration, ext::NumericalDuration};
553 /// assert_eq!(Duration::minutes(1), 60.seconds());
554 /// ```
555 ///
556 /// # Panics
557 ///
558 /// This may panic if an overflow occurs.
559 #[inline]
560 #[track_caller]
561 pub const fn minutes(minutes: i64) -> Self {
562 Self::seconds(
563 minutes
564 .checked_mul(Second::per_t(Minute))
565 .expect("overflow constructing `time::Duration`"),
566 )
567 }
568
569 /// Create a new `Duration` with the given number of seconds.
570 ///
571 /// ```rust
572 /// # use time::{Duration, ext::NumericalDuration};
573 /// assert_eq!(Duration::seconds(1), 1_000.milliseconds());
574 /// ```
575 #[inline]
576 pub const fn seconds(seconds: i64) -> Self {
577 Self::new_ranged_unchecked(seconds, Nanoseconds::new_static::<0>())
578 }
579
580 /// Create a new `Duration` from the specified number of seconds represented as `f64`.
581 ///
582 /// If the value is `NaN` or out of bounds, an error is returned that can be handled in the
583 /// desired manner by the caller.
584 #[inline]
585 const fn try_seconds_f64(seconds: f64) -> Result<Self, FloatConstructorError> {
586 try_from_secs!(
587 secs = seconds,
588 mantissa_bits = 52,
589 exponent_bits = 11,
590 offset = 44,
591 bits_ty = u64,
592 bits_ty_signed = i64,
593 double_ty = u128,
594 float_ty = f64,
595 )
596 }
597
598 /// Create a new `Duration` from the specified number of seconds represented as `f32`.
599 ///
600 /// If the value is `NaN` or out of bounds, an error is returned that can be handled in the
601 /// desired manner by the caller.
602 #[inline]
603 const fn try_seconds_f32(seconds: f32) -> Result<Self, FloatConstructorError> {
604 try_from_secs!(
605 secs = seconds,
606 mantissa_bits = 23,
607 exponent_bits = 8,
608 offset = 41,
609 bits_ty = u32,
610 bits_ty_signed = i32,
611 double_ty = u64,
612 float_ty = f32,
613 )
614 }
615
616 /// Creates a new `Duration` from the specified number of seconds represented as `f64`.
617 ///
618 /// ```rust
619 /// # use time::{Duration, ext::NumericalDuration};
620 /// assert_eq!(Duration::seconds_f64(0.5), 0.5.seconds());
621 /// assert_eq!(Duration::seconds_f64(-0.5), (-0.5).seconds());
622 /// ```
623 ///
624 /// # Panics
625 ///
626 /// This may panic if `seconds` is `NaN` or overflows the representable range of `Duration`.
627 #[inline]
628 #[track_caller]
629 pub const fn seconds_f64(seconds: f64) -> Self {
630 match Self::try_seconds_f64(seconds) {
631 Ok(duration) => duration,
632 Err(FloatConstructorError::Nan) => {
633 panic!("passed NaN to `time::Duration::seconds_f64`");
634 }
635 Err(FloatConstructorError::NegOverflow | FloatConstructorError::PosOverflow) => {
636 panic!("overflow constructing `time::Duration`");
637 }
638 }
639 }
640
641 /// Creates a new `Duration` from the specified number of seconds represented as `f32`.
642 ///
643 /// ```rust
644 /// # use time::{Duration, ext::NumericalDuration};
645 /// assert_eq!(Duration::seconds_f32(0.5), 0.5.seconds());
646 /// assert_eq!(Duration::seconds_f32(-0.5), (-0.5).seconds());
647 /// ```
648 ///
649 /// # Panics
650 ///
651 /// This may panic if `seconds` is `NaN` or overflows the representable range of `Duration`.
652 #[inline]
653 #[track_caller]
654 pub const fn seconds_f32(seconds: f32) -> Self {
655 match Self::try_seconds_f32(seconds) {
656 Ok(duration) => duration,
657 Err(FloatConstructorError::Nan) => {
658 panic!("passed NaN to `time::Duration::seconds_f32`");
659 }
660 Err(FloatConstructorError::NegOverflow | FloatConstructorError::PosOverflow) => {
661 panic!("overflow constructing `time::Duration`");
662 }
663 }
664 }
665
666 /// Creates a new `Duration` from the specified number of seconds
667 /// represented as `f64`. Any values that are out of bounds are saturated at
668 /// the minimum or maximum respectively. `NaN` gets turned into a `Duration`
669 /// of 0 seconds.
670 ///
671 /// ```rust
672 /// # use time::{Duration, ext::NumericalDuration};
673 /// assert_eq!(Duration::saturating_seconds_f64(0.5), 0.5.seconds());
674 /// assert_eq!(Duration::saturating_seconds_f64(-0.5), (-0.5).seconds());
675 /// assert_eq!(
676 /// Duration::saturating_seconds_f64(f64::NAN),
677 /// Duration::new(0, 0),
678 /// );
679 /// assert_eq!(
680 /// Duration::saturating_seconds_f64(f64::NEG_INFINITY),
681 /// Duration::MIN,
682 /// );
683 /// assert_eq!(
684 /// Duration::saturating_seconds_f64(f64::INFINITY),
685 /// Duration::MAX,
686 /// );
687 /// ```
688 #[inline]
689 pub const fn saturating_seconds_f64(seconds: f64) -> Self {
690 match Self::try_seconds_f64(seconds) {
691 Ok(duration) => duration,
692 Err(FloatConstructorError::Nan) => Self::ZERO,
693 Err(FloatConstructorError::NegOverflow) => Self::MIN,
694 Err(FloatConstructorError::PosOverflow) => Self::MAX,
695 }
696 }
697
698 /// Creates a new `Duration` from the specified number of seconds
699 /// represented as `f32`. Any values that are out of bounds are saturated at
700 /// the minimum or maximum respectively. `NaN` gets turned into a `Duration`
701 /// of 0 seconds.
702 ///
703 /// ```rust
704 /// # use time::{Duration, ext::NumericalDuration};
705 /// assert_eq!(Duration::saturating_seconds_f32(0.5), 0.5.seconds());
706 /// assert_eq!(Duration::saturating_seconds_f32(-0.5), (-0.5).seconds());
707 /// assert_eq!(
708 /// Duration::saturating_seconds_f32(f32::NAN),
709 /// Duration::new(0, 0),
710 /// );
711 /// assert_eq!(
712 /// Duration::saturating_seconds_f32(f32::NEG_INFINITY),
713 /// Duration::MIN,
714 /// );
715 /// assert_eq!(
716 /// Duration::saturating_seconds_f32(f32::INFINITY),
717 /// Duration::MAX,
718 /// );
719 /// ```
720 #[inline]
721 pub const fn saturating_seconds_f32(seconds: f32) -> Self {
722 match Self::try_seconds_f32(seconds) {
723 Ok(duration) => duration,
724 Err(FloatConstructorError::Nan) => Self::ZERO,
725 Err(FloatConstructorError::NegOverflow) => Self::MIN,
726 Err(FloatConstructorError::PosOverflow) => Self::MAX,
727 }
728 }
729
730 /// Creates a new `Duration` from the specified number of seconds
731 /// represented as `f64`. Returns `None` if the `Duration` can't be
732 /// represented.
733 ///
734 /// ```rust
735 /// # use time::{Duration, ext::NumericalDuration};
736 /// assert_eq!(Duration::checked_seconds_f64(0.5), Some(0.5.seconds()));
737 /// assert_eq!(Duration::checked_seconds_f64(-0.5), Some((-0.5).seconds()));
738 /// assert_eq!(Duration::checked_seconds_f64(f64::NAN), None);
739 /// assert_eq!(Duration::checked_seconds_f64(f64::NEG_INFINITY), None);
740 /// assert_eq!(Duration::checked_seconds_f64(f64::INFINITY), None);
741 /// ```
742 #[inline]
743 pub const fn checked_seconds_f64(seconds: f64) -> Option<Self> {
744 match Self::try_seconds_f64(seconds) {
745 Ok(duration) => Some(duration),
746 Err(_) => None,
747 }
748 }
749
750 /// Creates a new `Duration` from the specified number of seconds
751 /// represented as `f32`. Returns `None` if the `Duration` can't be
752 /// represented.
753 ///
754 /// ```rust
755 /// # use time::{Duration, ext::NumericalDuration};
756 /// assert_eq!(Duration::checked_seconds_f32(0.5), Some(0.5.seconds()));
757 /// assert_eq!(Duration::checked_seconds_f32(-0.5), Some((-0.5).seconds()));
758 /// assert_eq!(Duration::checked_seconds_f32(f32::NAN), None);
759 /// assert_eq!(Duration::checked_seconds_f32(f32::NEG_INFINITY), None);
760 /// assert_eq!(Duration::checked_seconds_f32(f32::INFINITY), None);
761 /// ```
762 #[inline]
763 pub const fn checked_seconds_f32(seconds: f32) -> Option<Self> {
764 match Self::try_seconds_f32(seconds) {
765 Ok(duration) => Some(duration),
766 Err(_) => None,
767 }
768 }
769
770 /// Create a new `Duration` with the given number of milliseconds.
771 ///
772 /// ```rust
773 /// # use time::{Duration, ext::NumericalDuration};
774 /// assert_eq!(Duration::milliseconds(1), 1_000.microseconds());
775 /// assert_eq!(Duration::milliseconds(-1), (-1_000).microseconds());
776 /// ```
777 #[inline]
778 pub const fn milliseconds(milliseconds: i64) -> Self {
779 // Safety: `nanoseconds` is guaranteed to be in range because of the modulus.
780 unsafe {
781 Self::new_unchecked(
782 milliseconds / Millisecond::per_t::<i64>(Second),
783 (milliseconds % Millisecond::per_t::<i64>(Second)
784 * Nanosecond::per_t::<i64>(Millisecond)) as i32,
785 )
786 }
787 }
788
789 /// Create a new `Duration` with the given number of microseconds.
790 ///
791 /// ```rust
792 /// # use time::{Duration, ext::NumericalDuration};
793 /// assert_eq!(Duration::microseconds(1), 1_000.nanoseconds());
794 /// assert_eq!(Duration::microseconds(-1), (-1_000).nanoseconds());
795 /// ```
796 #[inline]
797 pub const fn microseconds(microseconds: i64) -> Self {
798 // Safety: `nanoseconds` is guaranteed to be in range because of the modulus.
799 unsafe {
800 Self::new_unchecked(
801 microseconds / Microsecond::per_t::<i64>(Second),
802 (microseconds % Microsecond::per_t::<i64>(Second)
803 * Nanosecond::per_t::<i64>(Microsecond)) as i32,
804 )
805 }
806 }
807
808 /// Create a new `Duration` with the given number of nanoseconds.
809 ///
810 /// ```rust
811 /// # use time::{Duration, ext::NumericalDuration};
812 /// assert_eq!(Duration::nanoseconds(1), 1.microseconds() / 1_000);
813 /// assert_eq!(Duration::nanoseconds(-1), (-1).microseconds() / 1_000);
814 /// ```
815 #[inline]
816 pub const fn nanoseconds(nanoseconds: i64) -> Self {
817 // Safety: `nanoseconds` is guaranteed to be in range because of the modulus.
818 unsafe {
819 Self::new_unchecked(
820 nanoseconds / Nanosecond::per_t::<i64>(Second),
821 (nanoseconds % Nanosecond::per_t::<i64>(Second)) as i32,
822 )
823 }
824 }
825
826 /// Create a new `Duration` with the given number of nanoseconds.
827 ///
828 /// ```rust
829 /// # use time::{Duration, ext::NumericalDuration};
830 /// assert_eq!(
831 /// Duration::nanoseconds_i128(1_234_567_890),
832 /// 1.seconds() + 234_567_890.nanoseconds()
833 /// );
834 /// ```
835 ///
836 /// # Panics
837 ///
838 /// This may panic if an overflow occurs. This may happen because the input range cannot be
839 /// fully mapped to the output.
840 #[inline]
841 #[track_caller]
842 pub const fn nanoseconds_i128(nanoseconds: i128) -> Self {
843 let seconds = nanoseconds / Nanosecond::per_t::<i128>(Second);
844 let nanoseconds = nanoseconds % Nanosecond::per_t::<i128>(Second);
845
846 if seconds > i64::MAX as i128 || seconds < i64::MIN as i128 {
847 panic!("overflow constructing `time::Duration`");
848 }
849
850 // Safety: `nanoseconds` is guaranteed to be in range because of the modulus above.
851 unsafe { Self::new_unchecked(seconds as i64, nanoseconds as i32) }
852 }
853
854 /// Get the number of whole weeks in the duration.
855 ///
856 /// ```rust
857 /// # use time::ext::NumericalDuration;
858 /// assert_eq!(1.weeks().whole_weeks(), 1);
859 /// assert_eq!((-1).weeks().whole_weeks(), -1);
860 /// assert_eq!(6.days().whole_weeks(), 0);
861 /// assert_eq!((-6).days().whole_weeks(), 0);
862 /// ```
863 #[inline]
864 pub const fn whole_weeks(self) -> i64 {
865 self.whole_seconds() / Second::per_t::<i64>(Week)
866 }
867
868 /// Get the number of whole days in the duration.
869 ///
870 /// ```rust
871 /// # use time::ext::NumericalDuration;
872 /// assert_eq!(1.days().whole_days(), 1);
873 /// assert_eq!((-1).days().whole_days(), -1);
874 /// assert_eq!(23.hours().whole_days(), 0);
875 /// assert_eq!((-23).hours().whole_days(), 0);
876 /// ```
877 #[inline]
878 pub const fn whole_days(self) -> i64 {
879 self.whole_seconds() / Second::per_t::<i64>(Day)
880 }
881
882 /// Get the number of whole hours in the duration.
883 ///
884 /// ```rust
885 /// # use time::ext::NumericalDuration;
886 /// assert_eq!(1.hours().whole_hours(), 1);
887 /// assert_eq!((-1).hours().whole_hours(), -1);
888 /// assert_eq!(59.minutes().whole_hours(), 0);
889 /// assert_eq!((-59).minutes().whole_hours(), 0);
890 /// ```
891 #[inline]
892 pub const fn whole_hours(self) -> i64 {
893 self.whole_seconds() / Second::per_t::<i64>(Hour)
894 }
895
896 /// Get the number of whole minutes in the duration.
897 ///
898 /// ```rust
899 /// # use time::ext::NumericalDuration;
900 /// assert_eq!(1.minutes().whole_minutes(), 1);
901 /// assert_eq!((-1).minutes().whole_minutes(), -1);
902 /// assert_eq!(59.seconds().whole_minutes(), 0);
903 /// assert_eq!((-59).seconds().whole_minutes(), 0);
904 /// ```
905 #[inline]
906 pub const fn whole_minutes(self) -> i64 {
907 self.whole_seconds() / Second::per_t::<i64>(Minute)
908 }
909
910 /// Get the number of whole seconds in the duration.
911 ///
912 /// ```rust
913 /// # use time::ext::NumericalDuration;
914 /// assert_eq!(1.seconds().whole_seconds(), 1);
915 /// assert_eq!((-1).seconds().whole_seconds(), -1);
916 /// assert_eq!(1.minutes().whole_seconds(), 60);
917 /// assert_eq!((-1).minutes().whole_seconds(), -60);
918 /// ```
919 #[inline]
920 pub const fn whole_seconds(self) -> i64 {
921 self.seconds
922 }
923
924 /// Get the number of fractional seconds in the duration.
925 ///
926 /// ```rust
927 /// # use time::ext::NumericalDuration;
928 /// assert_eq!(1.5.seconds().as_seconds_f64(), 1.5);
929 /// assert_eq!((-1.5).seconds().as_seconds_f64(), -1.5);
930 /// ```
931 #[inline]
932 pub const fn as_seconds_f64(self) -> f64 {
933 self.seconds as f64 + self.nanoseconds.get() as f64 / Nanosecond::per_t::<f64>(Second)
934 }
935
936 /// Get the number of fractional seconds in the duration.
937 ///
938 /// ```rust
939 /// # use time::ext::NumericalDuration;
940 /// assert_eq!(1.5.seconds().as_seconds_f32(), 1.5);
941 /// assert_eq!((-1.5).seconds().as_seconds_f32(), -1.5);
942 /// ```
943 #[inline]
944 pub const fn as_seconds_f32(self) -> f32 {
945 self.seconds as f32 + self.nanoseconds.get() as f32 / Nanosecond::per_t::<f32>(Second)
946 }
947
948 /// Get the number of whole milliseconds in the duration.
949 ///
950 /// ```rust
951 /// # use time::ext::NumericalDuration;
952 /// assert_eq!(1.seconds().whole_milliseconds(), 1_000);
953 /// assert_eq!((-1).seconds().whole_milliseconds(), -1_000);
954 /// assert_eq!(1.milliseconds().whole_milliseconds(), 1);
955 /// assert_eq!((-1).milliseconds().whole_milliseconds(), -1);
956 /// ```
957 #[inline]
958 pub const fn whole_milliseconds(self) -> i128 {
959 self.seconds as i128 * Millisecond::per_t::<i128>(Second)
960 + self.nanoseconds.get() as i128 / Nanosecond::per_t::<i128>(Millisecond)
961 }
962
963 /// Get the number of milliseconds past the number of whole seconds.
964 ///
965 /// Always in the range `-999..=999`.
966 ///
967 /// ```rust
968 /// # use time::ext::NumericalDuration;
969 /// assert_eq!(1.4.seconds().subsec_milliseconds(), 400);
970 /// assert_eq!((-1.4).seconds().subsec_milliseconds(), -400);
971 /// ```
972 #[inline]
973 pub const fn subsec_milliseconds(self) -> i16 {
974 (self.nanoseconds.get() / Nanosecond::per_t::<i32>(Millisecond)) as i16
975 }
976
977 /// Get the number of whole microseconds in the duration.
978 ///
979 /// ```rust
980 /// # use time::ext::NumericalDuration;
981 /// assert_eq!(1.milliseconds().whole_microseconds(), 1_000);
982 /// assert_eq!((-1).milliseconds().whole_microseconds(), -1_000);
983 /// assert_eq!(1.microseconds().whole_microseconds(), 1);
984 /// assert_eq!((-1).microseconds().whole_microseconds(), -1);
985 /// ```
986 #[inline]
987 pub const fn whole_microseconds(self) -> i128 {
988 self.seconds as i128 * Microsecond::per_t::<i128>(Second)
989 + self.nanoseconds.get() as i128 / Nanosecond::per_t::<i128>(Microsecond)
990 }
991
992 /// Get the number of microseconds past the number of whole seconds.
993 ///
994 /// Always in the range `-999_999..=999_999`.
995 ///
996 /// ```rust
997 /// # use time::ext::NumericalDuration;
998 /// assert_eq!(1.0004.seconds().subsec_microseconds(), 400);
999 /// assert_eq!((-1.0004).seconds().subsec_microseconds(), -400);
1000 /// ```
1001 #[inline]
1002 pub const fn subsec_microseconds(self) -> i32 {
1003 self.nanoseconds.get() / Nanosecond::per_t::<i32>(Microsecond)
1004 }
1005
1006 /// Get the number of nanoseconds in the duration.
1007 ///
1008 /// ```rust
1009 /// # use time::ext::NumericalDuration;
1010 /// assert_eq!(1.microseconds().whole_nanoseconds(), 1_000);
1011 /// assert_eq!((-1).microseconds().whole_nanoseconds(), -1_000);
1012 /// assert_eq!(1.nanoseconds().whole_nanoseconds(), 1);
1013 /// assert_eq!((-1).nanoseconds().whole_nanoseconds(), -1);
1014 /// ```
1015 #[inline]
1016 pub const fn whole_nanoseconds(self) -> i128 {
1017 self.seconds as i128 * Nanosecond::per_t::<i128>(Second) + self.nanoseconds.get() as i128
1018 }
1019
1020 /// Get the number of nanoseconds past the number of whole seconds.
1021 ///
1022 /// The returned value will always be in the range `-999_999_999..=999_999_999`.
1023 ///
1024 /// ```rust
1025 /// # use time::ext::NumericalDuration;
1026 /// assert_eq!(1.000_000_400.seconds().subsec_nanoseconds(), 400);
1027 /// assert_eq!((-1.000_000_400).seconds().subsec_nanoseconds(), -400);
1028 /// ```
1029 #[inline]
1030 pub const fn subsec_nanoseconds(self) -> i32 {
1031 self.nanoseconds.get()
1032 }
1033
1034 /// Get the number of nanoseconds past the number of whole seconds.
1035 #[cfg(feature = "quickcheck")]
1036 #[inline]
1037 pub(crate) const fn subsec_nanoseconds_ranged(self) -> Nanoseconds {
1038 self.nanoseconds
1039 }
1040
1041 /// Computes `self + rhs`, returning `None` if an overflow occurred.
1042 ///
1043 /// ```rust
1044 /// # use time::{Duration, ext::NumericalDuration};
1045 /// assert_eq!(5.seconds().checked_add(5.seconds()), Some(10.seconds()));
1046 /// assert_eq!(Duration::MAX.checked_add(1.nanoseconds()), None);
1047 /// assert_eq!((-5).seconds().checked_add(5.seconds()), Some(0.seconds()));
1048 /// ```
1049 #[inline]
1050 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
1051 let mut seconds = const_try_opt!(self.seconds.checked_add(rhs.seconds));
1052 let mut nanoseconds = self.nanoseconds.get() + rhs.nanoseconds.get();
1053
1054 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
1055 nanoseconds -= Nanosecond::per_t::<i32>(Second);
1056 seconds = const_try_opt!(seconds.checked_add(1));
1057 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
1058 {
1059 nanoseconds += Nanosecond::per_t::<i32>(Second);
1060 seconds = const_try_opt!(seconds.checked_sub(1));
1061 }
1062
1063 // Safety: `nanoseconds` is guaranteed to be in range because of the overflow handling.
1064 unsafe { Some(Self::new_unchecked(seconds, nanoseconds)) }
1065 }
1066
1067 /// Computes `self - rhs`, returning `None` if an overflow occurred.
1068 ///
1069 /// ```rust
1070 /// # use time::{Duration, ext::NumericalDuration};
1071 /// assert_eq!(5.seconds().checked_sub(5.seconds()), Some(Duration::ZERO));
1072 /// assert_eq!(Duration::MIN.checked_sub(1.nanoseconds()), None);
1073 /// assert_eq!(5.seconds().checked_sub(10.seconds()), Some((-5).seconds()));
1074 /// ```
1075 #[inline]
1076 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
1077 let mut seconds = const_try_opt!(self.seconds.checked_sub(rhs.seconds));
1078 let mut nanoseconds = self.nanoseconds.get() - rhs.nanoseconds.get();
1079
1080 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
1081 nanoseconds -= Nanosecond::per_t::<i32>(Second);
1082 seconds = const_try_opt!(seconds.checked_add(1));
1083 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
1084 {
1085 nanoseconds += Nanosecond::per_t::<i32>(Second);
1086 seconds = const_try_opt!(seconds.checked_sub(1));
1087 }
1088
1089 // Safety: `nanoseconds` is guaranteed to be in range because of the overflow handling.
1090 unsafe { Some(Self::new_unchecked(seconds, nanoseconds)) }
1091 }
1092
1093 /// Computes `self * rhs`, returning `None` if an overflow occurred.
1094 ///
1095 /// ```rust
1096 /// # use time::{Duration, ext::NumericalDuration};
1097 /// assert_eq!(5.seconds().checked_mul(2), Some(10.seconds()));
1098 /// assert_eq!(5.seconds().checked_mul(-2), Some((-10).seconds()));
1099 /// assert_eq!(5.seconds().checked_mul(0), Some(0.seconds()));
1100 /// assert_eq!(Duration::MAX.checked_mul(2), None);
1101 /// assert_eq!(Duration::MIN.checked_mul(2), None);
1102 /// ```
1103 #[inline]
1104 pub const fn checked_mul(self, rhs: i32) -> Option<Self> {
1105 // Multiply nanoseconds as i64, because it cannot overflow that way.
1106 let total_nanos = self.nanoseconds.get() as i64 * rhs as i64;
1107 let extra_secs = total_nanos / Nanosecond::per_t::<i64>(Second);
1108 let nanoseconds = (total_nanos % Nanosecond::per_t::<i64>(Second)) as i32;
1109 let seconds = const_try_opt!(
1110 const_try_opt!(self.seconds.checked_mul(rhs as i64)).checked_add(extra_secs)
1111 );
1112
1113 // Safety: `nanoseconds` is guaranteed to be in range because of the modulus above.
1114 unsafe { Some(Self::new_unchecked(seconds, nanoseconds)) }
1115 }
1116
1117 /// Computes `self / rhs`, returning `None` if `rhs == 0` or if the result would overflow.
1118 ///
1119 /// ```rust
1120 /// # use time::ext::NumericalDuration;
1121 /// assert_eq!(10.seconds().checked_div(2), Some(5.seconds()));
1122 /// assert_eq!(10.seconds().checked_div(-2), Some((-5).seconds()));
1123 /// assert_eq!(1.seconds().checked_div(0), None);
1124 /// ```
1125 #[inline]
1126 pub const fn checked_div(self, rhs: i32) -> Option<Self> {
1127 let (secs, extra_secs) = (
1128 const_try_opt!(self.seconds.checked_div(rhs as i64)),
1129 self.seconds % (rhs as i64),
1130 );
1131 let (mut nanos, extra_nanos) = (self.nanoseconds.get() / rhs, self.nanoseconds.get() % rhs);
1132 nanos += ((extra_secs * (Nanosecond::per_t::<i64>(Second)) + extra_nanos as i64)
1133 / (rhs as i64)) as i32;
1134
1135 // Safety: `nanoseconds` is in range.
1136 unsafe { Some(Self::new_unchecked(secs, nanos)) }
1137 }
1138
1139 /// Computes `-self`, returning `None` if the result would overflow.
1140 ///
1141 /// ```rust
1142 /// # use time::ext::NumericalDuration;
1143 /// # use time::Duration;
1144 /// assert_eq!(5.seconds().checked_neg(), Some((-5).seconds()));
1145 /// assert_eq!(Duration::MIN.checked_neg(), None);
1146 /// ```
1147 #[inline]
1148 pub const fn checked_neg(self) -> Option<Self> {
1149 if self.seconds == i64::MIN {
1150 None
1151 } else {
1152 Some(Self::new_ranged_unchecked(
1153 -self.seconds,
1154 self.nanoseconds.neg(),
1155 ))
1156 }
1157 }
1158
1159 /// Computes `self + rhs`, saturating if an overflow occurred.
1160 ///
1161 /// ```rust
1162 /// # use time::{Duration, ext::NumericalDuration};
1163 /// assert_eq!(5.seconds().saturating_add(5.seconds()), 10.seconds());
1164 /// assert_eq!(Duration::MAX.saturating_add(1.nanoseconds()), Duration::MAX);
1165 /// assert_eq!(
1166 /// Duration::MIN.saturating_add((-1).nanoseconds()),
1167 /// Duration::MIN
1168 /// );
1169 /// assert_eq!((-5).seconds().saturating_add(5.seconds()), Duration::ZERO);
1170 /// ```
1171 #[inline]
1172 pub const fn saturating_add(self, rhs: Self) -> Self {
1173 let (mut seconds, overflow) = self.seconds.overflowing_add(rhs.seconds);
1174 if overflow {
1175 if self.seconds > 0 {
1176 return Self::MAX;
1177 }
1178 return Self::MIN;
1179 }
1180 let mut nanoseconds = self.nanoseconds.get() + rhs.nanoseconds.get();
1181
1182 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
1183 nanoseconds -= Nanosecond::per_t::<i32>(Second);
1184 seconds = match seconds.checked_add(1) {
1185 Some(seconds) => seconds,
1186 None => return Self::MAX,
1187 };
1188 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
1189 {
1190 nanoseconds += Nanosecond::per_t::<i32>(Second);
1191 seconds = match seconds.checked_sub(1) {
1192 Some(seconds) => seconds,
1193 None => return Self::MIN,
1194 };
1195 }
1196
1197 // Safety: `nanoseconds` is guaranteed to be in range because of the overflow handling.
1198 unsafe { Self::new_unchecked(seconds, nanoseconds) }
1199 }
1200
1201 /// Computes `self - rhs`, saturating if an overflow occurred.
1202 ///
1203 /// ```rust
1204 /// # use time::{Duration, ext::NumericalDuration};
1205 /// assert_eq!(5.seconds().saturating_sub(5.seconds()), Duration::ZERO);
1206 /// assert_eq!(Duration::MIN.saturating_sub(1.nanoseconds()), Duration::MIN);
1207 /// assert_eq!(
1208 /// Duration::MAX.saturating_sub((-1).nanoseconds()),
1209 /// Duration::MAX
1210 /// );
1211 /// assert_eq!(5.seconds().saturating_sub(10.seconds()), (-5).seconds());
1212 /// ```
1213 #[inline]
1214 pub const fn saturating_sub(self, rhs: Self) -> Self {
1215 let (mut seconds, overflow) = self.seconds.overflowing_sub(rhs.seconds);
1216 if overflow {
1217 if self.seconds > 0 {
1218 return Self::MAX;
1219 }
1220 return Self::MIN;
1221 }
1222 let mut nanoseconds = self.nanoseconds.get() - rhs.nanoseconds.get();
1223
1224 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
1225 nanoseconds -= Nanosecond::per_t::<i32>(Second);
1226 seconds = match seconds.checked_add(1) {
1227 Some(seconds) => seconds,
1228 None => return Self::MAX,
1229 };
1230 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
1231 {
1232 nanoseconds += Nanosecond::per_t::<i32>(Second);
1233 seconds = match seconds.checked_sub(1) {
1234 Some(seconds) => seconds,
1235 None => return Self::MIN,
1236 };
1237 }
1238
1239 // Safety: `nanoseconds` is guaranteed to be in range because of the overflow handling.
1240 unsafe { Self::new_unchecked(seconds, nanoseconds) }
1241 }
1242
1243 /// Computes `self * rhs`, saturating if an overflow occurred.
1244 ///
1245 /// ```rust
1246 /// # use time::{Duration, ext::NumericalDuration};
1247 /// assert_eq!(5.seconds().saturating_mul(2), 10.seconds());
1248 /// assert_eq!(5.seconds().saturating_mul(-2), (-10).seconds());
1249 /// assert_eq!(5.seconds().saturating_mul(0), Duration::ZERO);
1250 /// assert_eq!(Duration::MAX.saturating_mul(2), Duration::MAX);
1251 /// assert_eq!(Duration::MIN.saturating_mul(2), Duration::MIN);
1252 /// assert_eq!(Duration::MAX.saturating_mul(-2), Duration::MIN);
1253 /// assert_eq!(Duration::MIN.saturating_mul(-2), Duration::MAX);
1254 /// ```
1255 #[inline]
1256 pub const fn saturating_mul(self, rhs: i32) -> Self {
1257 // Multiply nanoseconds as i64, because it cannot overflow that way.
1258 let total_nanos = self.nanoseconds.get() as i64 * rhs as i64;
1259 let extra_secs = total_nanos / Nanosecond::per_t::<i64>(Second);
1260 let nanoseconds = (total_nanos % Nanosecond::per_t::<i64>(Second)) as i32;
1261 let (seconds, overflow1) = self.seconds.overflowing_mul(rhs as i64);
1262 if overflow1 {
1263 if self.seconds > 0 && rhs > 0 || self.seconds < 0 && rhs < 0 {
1264 return Self::MAX;
1265 }
1266 return Self::MIN;
1267 }
1268 let (seconds, overflow2) = seconds.overflowing_add(extra_secs);
1269 if overflow2 {
1270 if self.seconds > 0 && rhs > 0 {
1271 return Self::MAX;
1272 }
1273 return Self::MIN;
1274 }
1275
1276 // Safety: `nanoseconds` is guaranteed to be in range because of to the modulus above.
1277 unsafe { Self::new_unchecked(seconds, nanoseconds) }
1278 }
1279
1280 /// Runs a closure, returning the duration of time it took to run. The return value of the
1281 /// closure is provided in the second part of the tuple.
1282 #[cfg(feature = "std")]
1283 #[doc(hidden)]
1284 #[inline]
1285 #[track_caller]
1286 #[deprecated(
1287 since = "0.3.32",
1288 note = "extremely limited use case, not intended for benchmarking"
1289 )]
1290 #[expect(deprecated)]
1291 pub fn time_fn<T>(f: impl FnOnce() -> T) -> (Self, T) {
1292 let start = Instant::now();
1293 let return_value = f();
1294 let end = Instant::now();
1295
1296 (end - start, return_value)
1297 }
1298}
1299
1300/// The format returned by this implementation is not stable and must not be relied upon.
1301///
1302/// By default this produces an exact, full-precision printout of the duration.
1303/// For a concise, rounded printout instead, you can use the `.N` format specifier:
1304///
1305/// ```
1306/// # use time::Duration;
1307/// #
1308/// let duration = Duration::new(123456, 789011223);
1309/// println!("{duration:.3}");
1310/// ```
1311///
1312/// For the purposes of this implementation, a day is exactly 24 hours and a minute is exactly 60
1313/// seconds.
1314impl fmt::Display for Duration {
1315 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1316 if self.is_negative() {
1317 f.write_str("-")?;
1318 }
1319
1320 if let Some(_precision) = f.precision() {
1321 // Concise, rounded representation.
1322
1323 if self.is_zero() {
1324 // Write a zero value with the requested precision.
1325 return (0.).fmt(f).and_then(|_| f.write_str("s"));
1326 }
1327
1328 /// Format the first item that produces a value greater than 1 and then break.
1329 macro_rules! item {
1330 ($name:literal, $value:expr) => {
1331 let value = $value;
1332 if value >= 1.0 {
1333 return value.fmt(f).and_then(|_| f.write_str($name));
1334 }
1335 };
1336 }
1337
1338 // Even if this produces a de-normal float, because we're rounding we don't really care.
1339 let seconds = self.unsigned_abs().as_secs_f64();
1340
1341 item!("d", seconds / Second::per_t::<f64>(Day));
1342 item!("h", seconds / Second::per_t::<f64>(Hour));
1343 item!("m", seconds / Second::per_t::<f64>(Minute));
1344 item!("s", seconds);
1345 item!("ms", seconds * Millisecond::per_t::<f64>(Second));
1346 item!("µs", seconds * Microsecond::per_t::<f64>(Second));
1347 item!("ns", seconds * Nanosecond::per_t::<f64>(Second));
1348 } else {
1349 // Precise, but verbose representation.
1350
1351 if self.is_zero() {
1352 return f.write_str("0s");
1353 }
1354
1355 /// Format a single item.
1356 macro_rules! item {
1357 ($name:literal, $value:expr) => {
1358 match $value {
1359 0 => Ok(()),
1360 value => value.fmt(f).and_then(|_| f.write_str($name)),
1361 }
1362 };
1363 }
1364
1365 let seconds = self.seconds.unsigned_abs();
1366 let nanoseconds = self.nanoseconds.get().unsigned_abs();
1367
1368 item!("d", seconds / Second::per_t::<u64>(Day))?;
1369 item!(
1370 "h",
1371 seconds / Second::per_t::<u64>(Hour) % Hour::per_t::<u64>(Day)
1372 )?;
1373 item!(
1374 "m",
1375 seconds / Second::per_t::<u64>(Minute) % Minute::per_t::<u64>(Hour)
1376 )?;
1377 item!("s", seconds % Second::per_t::<u64>(Minute))?;
1378 item!("ms", nanoseconds / Nanosecond::per_t::<u32>(Millisecond))?;
1379 item!(
1380 "µs",
1381 nanoseconds / Nanosecond::per_t::<u32>(Microsecond)
1382 % Microsecond::per_t::<u32>(Millisecond)
1383 )?;
1384 item!("ns", nanoseconds % Nanosecond::per_t::<u32>(Microsecond))?;
1385 }
1386
1387 Ok(())
1388 }
1389}
1390
1391impl TryFrom<StdDuration> for Duration {
1392 type Error = error::ConversionRange;
1393
1394 #[inline]
1395 fn try_from(original: StdDuration) -> Result<Self, error::ConversionRange> {
1396 Ok(Self::new(
1397 original
1398 .as_secs()
1399 .try_into()
1400 .map_err(|_| error::ConversionRange)?,
1401 original.subsec_nanos().cast_signed(),
1402 ))
1403 }
1404}
1405
1406impl TryFrom<Duration> for StdDuration {
1407 type Error = error::ConversionRange;
1408
1409 #[inline]
1410 fn try_from(duration: Duration) -> Result<Self, error::ConversionRange> {
1411 Ok(Self::new(
1412 duration
1413 .seconds
1414 .try_into()
1415 .map_err(|_| error::ConversionRange)?,
1416 duration
1417 .nanoseconds
1418 .get()
1419 .try_into()
1420 .map_err(|_| error::ConversionRange)?,
1421 ))
1422 }
1423}
1424
1425impl Add for Duration {
1426 type Output = Self;
1427
1428 /// # Panics
1429 ///
1430 /// This may panic if an overflow occurs.
1431 #[inline]
1432 #[track_caller]
1433 fn add(self, rhs: Self) -> Self::Output {
1434 self.checked_add(rhs)
1435 .expect("overflow when adding durations")
1436 }
1437}
1438
1439impl Add<StdDuration> for Duration {
1440 type Output = Self;
1441
1442 /// # Panics
1443 ///
1444 /// This may panic if an overflow occurs.
1445 #[inline]
1446 #[track_caller]
1447 fn add(self, std_duration: StdDuration) -> Self::Output {
1448 self + Self::try_from(std_duration)
1449 .expect("overflow converting `std::time::Duration` to `time::Duration`")
1450 }
1451}
1452
1453impl Add<Duration> for StdDuration {
1454 type Output = Duration;
1455
1456 /// # Panics
1457 ///
1458 /// This may panic if an overflow occurs.
1459 #[inline]
1460 #[track_caller]
1461 fn add(self, rhs: Duration) -> Self::Output {
1462 rhs + self
1463 }
1464}
1465
1466impl AddAssign<Self> for Duration {
1467 /// # Panics
1468 ///
1469 /// This may panic if an overflow occurs.
1470 #[inline]
1471 #[track_caller]
1472 fn add_assign(&mut self, rhs: Self) {
1473 *self = *self + rhs;
1474 }
1475}
1476
1477impl AddAssign<StdDuration> for Duration {
1478 /// # Panics
1479 ///
1480 /// This may panic if an overflow occurs.
1481 #[inline]
1482 #[track_caller]
1483 fn add_assign(&mut self, rhs: StdDuration) {
1484 *self = *self + rhs;
1485 }
1486}
1487
1488impl AddAssign<Duration> for StdDuration {
1489 /// # Panics
1490 ///
1491 /// This may panic if the resulting addition cannot be represented.
1492 #[inline]
1493 #[track_caller]
1494 fn add_assign(&mut self, rhs: Duration) {
1495 *self = (*self + rhs).try_into().expect(
1496 "Cannot represent a resulting duration in std. Try `let x = x + rhs;`, which will \
1497 change the type.",
1498 );
1499 }
1500}
1501
1502impl Neg for Duration {
1503 type Output = Self;
1504
1505 /// # Panics
1506 ///
1507 /// This may panic if an overflow occurs.
1508 #[inline]
1509 #[track_caller]
1510 fn neg(self) -> Self::Output {
1511 self.checked_neg().expect("overflow when negating duration")
1512 }
1513}
1514
1515impl Sub for Duration {
1516 type Output = Self;
1517
1518 /// # Panics
1519 ///
1520 /// This may panic if an overflow occurs.
1521 #[inline]
1522 #[track_caller]
1523 fn sub(self, rhs: Self) -> Self::Output {
1524 self.checked_sub(rhs)
1525 .expect("overflow when subtracting durations")
1526 }
1527}
1528
1529impl Sub<StdDuration> for Duration {
1530 type Output = Self;
1531
1532 /// # Panics
1533 ///
1534 /// This may panic if an overflow occurs.
1535 #[inline]
1536 #[track_caller]
1537 fn sub(self, rhs: StdDuration) -> Self::Output {
1538 self - Self::try_from(rhs)
1539 .expect("overflow converting `std::time::Duration` to `time::Duration`")
1540 }
1541}
1542
1543impl Sub<Duration> for StdDuration {
1544 type Output = Duration;
1545
1546 /// # Panics
1547 ///
1548 /// This may panic if an overflow occurs.
1549 #[inline]
1550 #[track_caller]
1551 fn sub(self, rhs: Duration) -> Self::Output {
1552 Duration::try_from(self)
1553 .expect("overflow converting `std::time::Duration` to `time::Duration`")
1554 - rhs
1555 }
1556}
1557
1558impl SubAssign<Self> for Duration {
1559 /// # Panics
1560 ///
1561 /// This may panic if an overflow occurs.
1562 #[inline]
1563 #[track_caller]
1564 fn sub_assign(&mut self, rhs: Self) {
1565 *self = *self - rhs;
1566 }
1567}
1568
1569impl SubAssign<StdDuration> for Duration {
1570 /// # Panics
1571 ///
1572 /// This may panic if an overflow occurs.
1573 #[inline]
1574 #[track_caller]
1575 fn sub_assign(&mut self, rhs: StdDuration) {
1576 *self = *self - rhs;
1577 }
1578}
1579
1580impl SubAssign<Duration> for StdDuration {
1581 /// # Panics
1582 ///
1583 /// This may panic if the resulting subtraction can not be represented.
1584 #[inline]
1585 #[track_caller]
1586 fn sub_assign(&mut self, rhs: Duration) {
1587 *self = (*self - rhs).try_into().expect(
1588 "Cannot represent a resulting duration in std. Try `let x = x - rhs;`, which will \
1589 change the type.",
1590 );
1591 }
1592}
1593
1594/// Given a value and whether it is signed, cast it to the signed version.
1595macro_rules! cast_signed {
1596 (@signed $val:ident) => {
1597 $val
1598 };
1599 (@unsigned $val:ident) => {
1600 $val.cast_signed()
1601 };
1602}
1603
1604/// Implement `Mul` (reflexively), `MulAssign`, `Div`, and `DivAssign` for `Duration` for various
1605/// signed types.
1606macro_rules! duration_mul_div_int {
1607 ($(@$signedness:ident $type:ty),+ $(,)?) => {$(
1608 impl Mul<$type> for Duration {
1609 type Output = Self;
1610
1611 /// # Panics
1612 ///
1613 /// This may panic if an overflow occurs.
1614 #[inline]
1615 #[track_caller]
1616 fn mul(self, rhs: $type) -> Self::Output {
1617 Self::nanoseconds_i128(
1618 self.whole_nanoseconds()
1619 .checked_mul(cast_signed!(@$signedness rhs).widen::<i128>())
1620 .expect("overflow when multiplying duration")
1621 )
1622 }
1623 }
1624
1625 impl Mul<Duration> for $type {
1626 type Output = Duration;
1627
1628 /// # Panics
1629 ///
1630 /// This may panic if an overflow occurs.
1631 #[inline]
1632 #[track_caller]
1633 fn mul(self, rhs: Duration) -> Self::Output {
1634 rhs * self
1635 }
1636 }
1637
1638 impl MulAssign<$type> for Duration {
1639 /// # Panics
1640 ///
1641 /// This may panic if an overflow occurs.
1642 #[inline]
1643 #[track_caller]
1644 fn mul_assign(&mut self, rhs: $type) {
1645 *self = *self * rhs;
1646 }
1647 }
1648
1649 impl Div<$type> for Duration {
1650 type Output = Self;
1651
1652 /// # Panics
1653 ///
1654 /// This may panic if an overflow occurs or if `rhs == 0`.
1655 #[inline]
1656 #[track_caller]
1657 fn div(self, rhs: $type) -> Self::Output {
1658 Self::nanoseconds_i128(
1659 self.whole_nanoseconds() / cast_signed!(@$signedness rhs).widen::<i128>()
1660 )
1661 }
1662 }
1663
1664 impl DivAssign<$type> for Duration {
1665 /// # Panics
1666 ///
1667 /// This may panic if an overflow occurs or if `rhs == 0`.
1668 #[inline]
1669 #[track_caller]
1670 fn div_assign(&mut self, rhs: $type) {
1671 *self = *self / rhs;
1672 }
1673 }
1674 )+};
1675}
1676
1677duration_mul_div_int! {
1678 @signed i8,
1679 @signed i16,
1680 @signed i32,
1681 @unsigned u8,
1682 @unsigned u16,
1683 @unsigned u32,
1684}
1685
1686impl Mul<f32> for Duration {
1687 type Output = Self;
1688
1689 /// # Panics
1690 ///
1691 /// This may panic if an overflow occurs.
1692 #[inline]
1693 #[track_caller]
1694 fn mul(self, rhs: f32) -> Self::Output {
1695 Self::seconds_f32(self.as_seconds_f32() * rhs)
1696 }
1697}
1698
1699impl Mul<Duration> for f32 {
1700 type Output = Duration;
1701
1702 /// # Panics
1703 ///
1704 /// This may panic if an overflow occurs.
1705 #[inline]
1706 #[track_caller]
1707 fn mul(self, rhs: Duration) -> Self::Output {
1708 rhs * self
1709 }
1710}
1711
1712impl Mul<f64> for Duration {
1713 type Output = Self;
1714
1715 /// # Panics
1716 ///
1717 /// This may panic if an overflow occurs.
1718 #[inline]
1719 #[track_caller]
1720 fn mul(self, rhs: f64) -> Self::Output {
1721 Self::seconds_f64(self.as_seconds_f64() * rhs)
1722 }
1723}
1724
1725impl Mul<Duration> for f64 {
1726 type Output = Duration;
1727
1728 /// # Panics
1729 ///
1730 /// This may panic if an overflow occurs.
1731 #[inline]
1732 #[track_caller]
1733 fn mul(self, rhs: Duration) -> Self::Output {
1734 rhs * self
1735 }
1736}
1737
1738impl MulAssign<f32> for Duration {
1739 /// # Panics
1740 ///
1741 /// This may panic if an overflow occurs.
1742 #[inline]
1743 #[track_caller]
1744 fn mul_assign(&mut self, rhs: f32) {
1745 *self = *self * rhs;
1746 }
1747}
1748
1749impl MulAssign<f64> for Duration {
1750 /// # Panics
1751 ///
1752 /// This may panic if an overflow occurs.
1753 #[inline]
1754 #[track_caller]
1755 fn mul_assign(&mut self, rhs: f64) {
1756 *self = *self * rhs;
1757 }
1758}
1759
1760impl Div<f32> for Duration {
1761 type Output = Self;
1762
1763 /// # Panics
1764 ///
1765 /// This may panic if an overflow occurs or if `rhs == 0`.
1766 #[inline]
1767 #[track_caller]
1768 fn div(self, rhs: f32) -> Self::Output {
1769 Self::seconds_f32(self.as_seconds_f32() / rhs)
1770 }
1771}
1772
1773impl Div<f64> for Duration {
1774 type Output = Self;
1775
1776 /// # Panics
1777 ///
1778 /// This may panic if an overflow occurs or if `rhs == 0`.
1779 #[inline]
1780 #[track_caller]
1781 fn div(self, rhs: f64) -> Self::Output {
1782 Self::seconds_f64(self.as_seconds_f64() / rhs)
1783 }
1784}
1785
1786impl DivAssign<f32> for Duration {
1787 /// # Panics
1788 ///
1789 /// This may panic if an overflow occurs or if `rhs == 0`.
1790 #[inline]
1791 #[track_caller]
1792 fn div_assign(&mut self, rhs: f32) {
1793 *self = *self / rhs;
1794 }
1795}
1796
1797impl DivAssign<f64> for Duration {
1798 /// # Panics
1799 ///
1800 /// This may panic if an overflow occurs or if `rhs == 0`.
1801 #[inline]
1802 #[track_caller]
1803 fn div_assign(&mut self, rhs: f64) {
1804 *self = *self / rhs;
1805 }
1806}
1807
1808impl Div for Duration {
1809 type Output = f64;
1810
1811 /// # Panics
1812 ///
1813 /// This may panic if `rhs == Duration::ZERO`.
1814 #[inline]
1815 #[track_caller]
1816 fn div(self, rhs: Self) -> Self::Output {
1817 self.as_seconds_f64() / rhs.as_seconds_f64()
1818 }
1819}
1820
1821impl Div<StdDuration> for Duration {
1822 type Output = f64;
1823
1824 /// # Panics
1825 ///
1826 /// This may panic if `rhs == Duration::ZERO`.
1827 #[inline]
1828 #[track_caller]
1829 fn div(self, rhs: StdDuration) -> Self::Output {
1830 self.as_seconds_f64() / rhs.as_secs_f64()
1831 }
1832}
1833
1834impl Div<Duration> for StdDuration {
1835 type Output = f64;
1836
1837 /// # Panics
1838 ///
1839 /// This may panic if `rhs == Duration::ZERO`.
1840 #[inline]
1841 #[track_caller]
1842 fn div(self, rhs: Duration) -> Self::Output {
1843 self.as_secs_f64() / rhs.as_seconds_f64()
1844 }
1845}
1846
1847impl PartialEq<StdDuration> for Duration {
1848 #[inline]
1849 fn eq(&self, rhs: &StdDuration) -> bool {
1850 Ok(*self) == Self::try_from(*rhs)
1851 }
1852}
1853
1854impl PartialEq<Duration> for StdDuration {
1855 #[inline]
1856 fn eq(&self, rhs: &Duration) -> bool {
1857 rhs == self
1858 }
1859}
1860
1861impl PartialOrd<StdDuration> for Duration {
1862 #[inline]
1863 fn partial_cmp(&self, rhs: &StdDuration) -> Option<Ordering> {
1864 if rhs.as_secs() > i64::MAX.cast_unsigned() {
1865 return Some(Ordering::Less);
1866 }
1867
1868 Some(
1869 self.seconds
1870 .cmp(&rhs.as_secs().cast_signed())
1871 .then_with(|| {
1872 self.nanoseconds
1873 .get()
1874 .cmp(&rhs.subsec_nanos().cast_signed())
1875 }),
1876 )
1877 }
1878}
1879
1880impl PartialOrd<Duration> for StdDuration {
1881 #[inline]
1882 fn partial_cmp(&self, rhs: &Duration) -> Option<Ordering> {
1883 rhs.partial_cmp(self).map(Ordering::reverse)
1884 }
1885}
1886
1887impl Sum for Duration {
1888 #[inline]
1889 fn sum<I>(iter: I) -> Self
1890 where
1891 I: Iterator<Item = Self>,
1892 {
1893 iter.reduce(|a, b| a + b).unwrap_or_default()
1894 }
1895}
1896
1897impl<'a> Sum<&'a Self> for Duration {
1898 #[inline]
1899 fn sum<I>(iter: I) -> Self
1900 where
1901 I: Iterator<Item = &'a Self>,
1902 {
1903 iter.copied().sum()
1904 }
1905}
1906
1907#[cfg(feature = "std")]
1908impl Add<Duration> for SystemTime {
1909 type Output = Self;
1910
1911 /// # Panics
1912 ///
1913 /// This may panic if an overflow occurs.
1914 #[inline]
1915 #[track_caller]
1916 fn add(self, duration: Duration) -> Self::Output {
1917 if duration.is_zero() {
1918 self
1919 } else if duration.is_positive() {
1920 self + duration.unsigned_abs()
1921 } else {
1922 debug_assert!(duration.is_negative());
1923 self - duration.unsigned_abs()
1924 }
1925 }
1926}
1927
1928#[cfg(feature = "std")]
1929impl AddAssign<Duration> for SystemTime {
1930 /// # Panics
1931 ///
1932 /// This may panic if an overflow occurs.
1933 #[inline]
1934 #[track_caller]
1935 fn add_assign(&mut self, rhs: Duration) {
1936 *self = *self + rhs;
1937 }
1938}
1939
1940#[cfg(feature = "std")]
1941impl Sub<Duration> for SystemTime {
1942 type Output = Self;
1943
1944 #[inline]
1945 #[track_caller]
1946 fn sub(self, duration: Duration) -> Self::Output {
1947 if duration.is_zero() {
1948 self
1949 } else if duration.is_positive() {
1950 self - duration.unsigned_abs()
1951 } else {
1952 debug_assert!(duration.is_negative());
1953 self + duration.unsigned_abs()
1954 }
1955 }
1956}
1957
1958#[cfg(feature = "std")]
1959impl SubAssign<Duration> for SystemTime {
1960 /// # Panics
1961 ///
1962 /// This may panic if an overflow occurs.
1963 #[inline]
1964 #[track_caller]
1965 fn sub_assign(&mut self, rhs: Duration) {
1966 *self = *self - rhs;
1967 }
1968}