Coverage Report

Created: 2025-07-23 06:21

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