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