Coverage Report

Created: 2026-01-17 07:12

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