Coverage Report

Created: 2026-04-12 07:07

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