time/duration.rs
1//! The [`Duration`] struct and its associated `impl`s.
2
3use core::cmp::Ordering;
4use core::fmt;
5use core::iter::Sum;
6use core::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
7use core::time::Duration as StdDuration;
8#[cfg(feature = "std")]
9use std::time::SystemTime;
10
11use deranged::RangedI32;
12use num_conv::prelude::*;
13
14use crate::convert::*;
15use crate::error;
16use 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)]
21use 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)]
27pub(crate) enum Padding {
28 #[allow(clippy::missing_docs_in_private_items)]
29 Optimize,
30}
31
32/// The type of the `nanosecond` field of `Duration`.
33type Nanoseconds =
34 RangedI32<{ -Nanosecond::per_t::<i32>(Second) + 1 }, { Nanosecond::per_t::<i32>(Second) - 1 }>;
35
36/// A span of time with nanosecond precision.
37///
38/// Each `Duration` is composed of a whole number of seconds and a fractional part represented in
39/// nanoseconds.
40///
41/// This implementation allows for negative durations, unlike [`core::time::Duration`].
42#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
43pub 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
52impl fmt::Debug for Duration {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 f.debug_struct("Duration")
55 .field("seconds", &self.seconds)
56 .field("nanoseconds", &self.nanoseconds)
57 .finish()
58 }
59}
60
61impl Default for Duration {
62 fn default() -> Self {
63 Self {
64 seconds: 0,
65 nanoseconds: Nanoseconds::new_static::<0>(),
66 padding: Padding::Optimize,
67 }
68 }
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.
78macro_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 = Nanosecond::per_t::<u128>(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_t(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 = Nanosecond::per_t::<$double_ty>(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_t(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
192impl 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 pub const fn is_zero(self) -> bool {
279 self.seconds == 0 && self.nanoseconds.get() == 0
280 }
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 pub const fn is_negative(self) -> bool {
291 self.seconds < 0 || self.nanoseconds.get() < 0
292 }
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 pub const fn is_positive(self) -> bool {
303 self.seconds > 0 || self.nanoseconds.get() > 0
304 }
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 pub const fn abs(self) -> Self {
317 match self.seconds.checked_abs() {
318 Some(seconds) => Self::new_ranged_unchecked(seconds, self.nanoseconds.abs()),
319 None => Self::MAX,
320 }
321 }
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 pub const fn unsigned_abs(self) -> StdDuration {
333 StdDuration::new(
334 self.seconds.unsigned_abs(),
335 self.nanoseconds.get().unsigned_abs(),
336 )
337 }
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 pub(crate) const unsafe fn new_unchecked(seconds: i64, nanoseconds: i32) -> Self {
348 Self::new_ranged_unchecked(
349 seconds,
350 // Safety: The caller must uphold the safety invariants.
351 unsafe { Nanoseconds::new_unchecked(nanoseconds) },
352 )
353 }
354
355 /// Create a new `Duration` without checking the validity of the components.
356 pub(crate) const fn new_ranged_unchecked(seconds: i64, nanoseconds: Nanoseconds) -> Self {
357 if seconds < 0 {
358 debug_assert!(nanoseconds.get() <= 0);
359 } else if seconds > 0 {
360 debug_assert!(nanoseconds.get() >= 0);
361 }
362
363 Self {
364 seconds,
365 nanoseconds,
366 padding: Padding::Optimize,
367 }
368 }
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 pub const fn new(mut seconds: i64, mut nanoseconds: i32) -> Self {
384 seconds = expect_opt!(
385 seconds.checked_add(nanoseconds as i64 / Nanosecond::per_t::<i64>(Second)),
386 "overflow constructing `time::Duration`"
387 );
388 nanoseconds %= Nanosecond::per_t::<i32>(Second);
389
390 if seconds > 0 && nanoseconds < 0 {
391 // `seconds` cannot overflow here because it is positive.
392 seconds -= 1;
393 nanoseconds += Nanosecond::per_t::<i32>(Second);
394 } else if seconds < 0 && nanoseconds > 0 {
395 // `seconds` cannot overflow here because it is negative.
396 seconds += 1;
397 nanoseconds -= Nanosecond::per_t::<i32>(Second);
398 }
399
400 // Safety: `nanoseconds` is in range due to the modulus above.
401 unsafe { Self::new_unchecked(seconds, nanoseconds) }
402 }
403
404 /// Create a new `Duration` with the provided seconds and nanoseconds.
405 pub(crate) const fn new_ranged(mut seconds: i64, mut nanoseconds: Nanoseconds) -> Self {
406 if seconds > 0 && nanoseconds.get() < 0 {
407 // `seconds` cannot overflow here because it is positive.
408 seconds -= 1;
409 // Safety: `nanoseconds` is negative with a maximum of 999,999,999, so adding a billion
410 // to it is guaranteed to result in an in-range value.
411 nanoseconds = unsafe {
412 Nanoseconds::new_unchecked(nanoseconds.get() + Nanosecond::per_t::<i32>(Second))
413 };
414 } else if seconds < 0 && nanoseconds.get() > 0 {
415 // `seconds` cannot overflow here because it is negative.
416 seconds += 1;
417 // Safety: `nanoseconds` is positive with a minimum of -999,999,999, so subtracting a
418 // billion from it is guaranteed to result in an in-range value.
419 nanoseconds = unsafe {
420 Nanoseconds::new_unchecked(nanoseconds.get() - Nanosecond::per_t::<i32>(Second))
421 };
422 }
423
424 Self::new_ranged_unchecked(seconds, nanoseconds)
425 }
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 pub const fn weeks(weeks: i64) -> Self {
439 Self::seconds(expect_opt!(
440 weeks.checked_mul(Second::per_t(Week)),
441 "overflow constructing `time::Duration`"
442 ))
443 }
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 pub const fn days(days: i64) -> Self {
457 Self::seconds(expect_opt!(
458 days.checked_mul(Second::per_t(Day)),
459 "overflow constructing `time::Duration`"
460 ))
461 }
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 pub const fn hours(hours: i64) -> Self {
475 Self::seconds(expect_opt!(
476 hours.checked_mul(Second::per_t(Hour)),
477 "overflow constructing `time::Duration`"
478 ))
479 }
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 pub const fn minutes(minutes: i64) -> Self {
493 Self::seconds(expect_opt!(
494 minutes.checked_mul(Second::per_t(Minute)),
495 "overflow constructing `time::Duration`"
496 ))
497 }
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 pub const fn seconds(seconds: i64) -> Self {
506 Self::new_ranged_unchecked(seconds, Nanoseconds::new_static::<0>())
507 }
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 pub fn seconds_f64(seconds: f64) -> Self {
517 try_from_secs!(
518 secs = seconds,
519 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 is_nan = crate::expect_failed("passed NaN to `time::Duration::seconds_f64`"),
527 is_overflow = crate::expect_failed("overflow constructing `time::Duration`"),
528 )
529 }
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 pub fn seconds_f32(seconds: f32) -> Self {
539 try_from_secs!(
540 secs = seconds,
541 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 is_nan = crate::expect_failed("passed NaN to `time::Duration::seconds_f32`"),
549 is_overflow = crate::expect_failed("overflow constructing `time::Duration`"),
550 )
551 }
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 pub fn saturating_seconds_f64(seconds: f64) -> Self {
576 try_from_secs!(
577 secs = seconds,
578 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 is_nan = return Self::ZERO,
586 is_overflow = return if seconds < 0.0 { Self::MIN } else { Self::MAX },
587 )
588 }
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 pub fn saturating_seconds_f32(seconds: f32) -> Self {
613 try_from_secs!(
614 secs = seconds,
615 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 is_nan = return Self::ZERO,
623 is_overflow = return if seconds < 0.0 { Self::MIN } else { Self::MAX },
624 )
625 }
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 pub fn checked_seconds_f64(seconds: f64) -> Option<Self> {
640 Some(try_from_secs!(
641 secs = seconds,
642 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 is_nan = return None,
650 is_overflow = return None,
651 ))
652 }
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 pub fn checked_seconds_f32(seconds: f32) -> Option<Self> {
667 Some(try_from_secs!(
668 secs = seconds,
669 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 is_nan = return None,
677 is_overflow = return None,
678 ))
679 }
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 pub const fn milliseconds(milliseconds: i64) -> Self {
689 // Safety: `nanoseconds` is guaranteed to be in range because of the modulus.
690 unsafe {
691 Self::new_unchecked(
692 milliseconds / Millisecond::per_t::<i64>(Second),
693 (milliseconds % Millisecond::per_t::<i64>(Second)
694 * Nanosecond::per_t::<i64>(Millisecond)) as i32,
695 )
696 }
697 }
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 pub const fn microseconds(microseconds: i64) -> Self {
707 // Safety: `nanoseconds` is guaranteed to be in range because of the modulus.
708 unsafe {
709 Self::new_unchecked(
710 microseconds / Microsecond::per_t::<i64>(Second),
711 (microseconds % Microsecond::per_t::<i64>(Second)
712 * Nanosecond::per_t::<i64>(Microsecond)) as i32,
713 )
714 }
715 }
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 pub const fn nanoseconds(nanoseconds: i64) -> Self {
725 // Safety: `nanoseconds` is guaranteed to be in range because of the modulus.
726 unsafe {
727 Self::new_unchecked(
728 nanoseconds / Nanosecond::per_t::<i64>(Second),
729 (nanoseconds % Nanosecond::per_t::<i64>(Second)) as i32,
730 )
731 }
732 }
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 pub(crate) const fn nanoseconds_i128(nanoseconds: i128) -> Self {
739 let seconds = nanoseconds / Nanosecond::per_t::<i128>(Second);
740 let nanoseconds = nanoseconds % Nanosecond::per_t::<i128>(Second);
741
742 if seconds > i64::MAX as i128 || seconds < i64::MIN as i128 {
743 crate::expect_failed("overflow constructing `time::Duration`");
744 }
745
746 // Safety: `nanoseconds` is guaranteed to be in range because of the modulus above.
747 unsafe { Self::new_unchecked(seconds as i64, nanoseconds as i32) }
748 }
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 pub const fn whole_weeks(self) -> i64 {
760 self.whole_seconds() / Second::per_t::<i64>(Week)
761 }
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 pub const fn whole_days(self) -> i64 {
773 self.whole_seconds() / Second::per_t::<i64>(Day)
774 }
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 pub const fn whole_hours(self) -> i64 {
786 self.whole_seconds() / Second::per_t::<i64>(Hour)
787 }
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 pub const fn whole_minutes(self) -> i64 {
799 self.whole_seconds() / Second::per_t::<i64>(Minute)
800 }
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 pub const fn whole_seconds(self) -> i64 {
812 self.seconds
813 }
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 pub fn as_seconds_f64(self) -> f64 {
823 self.seconds as f64 + self.nanoseconds.get() as f64 / Nanosecond::per_t::<f64>(Second)
824 }
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 pub fn as_seconds_f32(self) -> f32 {
834 self.seconds as f32 + self.nanoseconds.get() as f32 / Nanosecond::per_t::<f32>(Second)
835 }
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 pub const fn whole_milliseconds(self) -> i128 {
847 self.seconds as i128 * Millisecond::per_t::<i128>(Second)
848 + self.nanoseconds.get() as i128 / Nanosecond::per_t::<i128>(Millisecond)
849 }
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 pub const fn subsec_milliseconds(self) -> i16 {
862 (self.nanoseconds.get() / Nanosecond::per_t::<i32>(Millisecond)) as i16
863 }
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 pub const fn whole_microseconds(self) -> i128 {
875 self.seconds as i128 * Microsecond::per_t::<i128>(Second)
876 + self.nanoseconds.get() as i128 / Nanosecond::per_t::<i128>(Microsecond)
877 }
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 pub const fn subsec_microseconds(self) -> i32 {
889 self.nanoseconds.get() / Nanosecond::per_t::<i32>(Microsecond)
890 }
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 pub const fn whole_nanoseconds(self) -> i128 {
902 self.seconds as i128 * Nanosecond::per_t::<i128>(Second) + self.nanoseconds.get() as i128
903 }
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 pub const fn subsec_nanoseconds(self) -> i32 {
915 self.nanoseconds.get()
916 }
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 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
933 let mut seconds = const_try_opt!(self.seconds.checked_add(rhs.seconds));
934 let mut nanoseconds = self.nanoseconds.get() + rhs.nanoseconds.get();
935
936 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
937 nanoseconds -= Nanosecond::per_t::<i32>(Second);
938 seconds = const_try_opt!(seconds.checked_add(1));
939 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
940 {
941 nanoseconds += Nanosecond::per_t::<i32>(Second);
942 seconds = const_try_opt!(seconds.checked_sub(1));
943 }
944
945 // Safety: `nanoseconds` is guaranteed to be in range because of the overflow handling.
946 unsafe { Some(Self::new_unchecked(seconds, nanoseconds)) }
947 }
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 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
958 let mut seconds = const_try_opt!(self.seconds.checked_sub(rhs.seconds));
959 let mut nanoseconds = self.nanoseconds.get() - rhs.nanoseconds.get();
960
961 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
962 nanoseconds -= Nanosecond::per_t::<i32>(Second);
963 seconds = const_try_opt!(seconds.checked_add(1));
964 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
965 {
966 nanoseconds += Nanosecond::per_t::<i32>(Second);
967 seconds = const_try_opt!(seconds.checked_sub(1));
968 }
969
970 // Safety: `nanoseconds` is guaranteed to be in range because of the overflow handling.
971 unsafe { Some(Self::new_unchecked(seconds, nanoseconds)) }
972 }
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 pub const fn checked_mul(self, rhs: i32) -> Option<Self> {
985 // Multiply nanoseconds as i64, because it cannot overflow that way.
986 let total_nanos = self.nanoseconds.get() as i64 * rhs as i64;
987 let extra_secs = total_nanos / Nanosecond::per_t::<i64>(Second);
988 let nanoseconds = (total_nanos % Nanosecond::per_t::<i64>(Second)) as i32;
989 let seconds = const_try_opt!(
990 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 unsafe { Some(Self::new_unchecked(seconds, nanoseconds)) }
995 }
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 pub const fn checked_div(self, rhs: i32) -> Option<Self> {
1006 let (secs, extra_secs) = (
1007 const_try_opt!(self.seconds.checked_div(rhs as i64)),
1008 self.seconds % (rhs as i64),
1009 );
1010 let (mut nanos, extra_nanos) = (self.nanoseconds.get() / rhs, self.nanoseconds.get() % rhs);
1011 nanos += ((extra_secs * (Nanosecond::per_t::<i64>(Second)) + extra_nanos as i64)
1012 / (rhs as i64)) as i32;
1013
1014 // Safety: `nanoseconds` is in range.
1015 unsafe { Some(Self::new_unchecked(secs, nanos)) }
1016 }
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 pub const fn checked_neg(self) -> Option<Self> {
1027 if self.seconds == i64::MIN {
1028 None
1029 } else {
1030 Some(Self::new_ranged_unchecked(
1031 -self.seconds,
1032 self.nanoseconds.neg(),
1033 ))
1034 }
1035 }
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 pub const fn saturating_add(self, rhs: Self) -> Self {
1050 let (mut seconds, overflow) = self.seconds.overflowing_add(rhs.seconds);
1051 if overflow {
1052 if self.seconds > 0 {
1053 return Self::MAX;
1054 }
1055 return Self::MIN;
1056 }
1057 let mut nanoseconds = self.nanoseconds.get() + rhs.nanoseconds.get();
1058
1059 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
1060 nanoseconds -= Nanosecond::per_t::<i32>(Second);
1061 seconds = match seconds.checked_add(1) {
1062 Some(seconds) => seconds,
1063 None => return Self::MAX,
1064 };
1065 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
1066 {
1067 nanoseconds += Nanosecond::per_t::<i32>(Second);
1068 seconds = match seconds.checked_sub(1) {
1069 Some(seconds) => seconds,
1070 None => return Self::MIN,
1071 };
1072 }
1073
1074 // Safety: `nanoseconds` is guaranteed to be in range because of the overflow handling.
1075 unsafe { Self::new_unchecked(seconds, nanoseconds) }
1076 }
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 pub const fn saturating_sub(self, rhs: Self) -> Self {
1091 let (mut seconds, overflow) = self.seconds.overflowing_sub(rhs.seconds);
1092 if overflow {
1093 if self.seconds > 0 {
1094 return Self::MAX;
1095 }
1096 return Self::MIN;
1097 }
1098 let mut nanoseconds = self.nanoseconds.get() - rhs.nanoseconds.get();
1099
1100 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
1101 nanoseconds -= Nanosecond::per_t::<i32>(Second);
1102 seconds = match seconds.checked_add(1) {
1103 Some(seconds) => seconds,
1104 None => return Self::MAX,
1105 };
1106 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
1107 {
1108 nanoseconds += Nanosecond::per_t::<i32>(Second);
1109 seconds = match seconds.checked_sub(1) {
1110 Some(seconds) => seconds,
1111 None => return Self::MIN,
1112 };
1113 }
1114
1115 // Safety: `nanoseconds` is guaranteed to be in range because of the overflow handling.
1116 unsafe { Self::new_unchecked(seconds, nanoseconds) }
1117 }
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 pub const fn saturating_mul(self, rhs: i32) -> Self {
1132 // Multiply nanoseconds as i64, because it cannot overflow that way.
1133 let total_nanos = self.nanoseconds.get() as i64 * rhs as i64;
1134 let extra_secs = total_nanos / Nanosecond::per_t::<i64>(Second);
1135 let nanoseconds = (total_nanos % Nanosecond::per_t::<i64>(Second)) as i32;
1136 let (seconds, overflow1) = self.seconds.overflowing_mul(rhs as i64);
1137 if overflow1 {
1138 if self.seconds > 0 && rhs > 0 || self.seconds < 0 && rhs < 0 {
1139 return Self::MAX;
1140 }
1141 return Self::MIN;
1142 }
1143 let (seconds, overflow2) = seconds.overflowing_add(extra_secs);
1144 if overflow2 {
1145 if self.seconds > 0 && rhs > 0 {
1146 return Self::MAX;
1147 }
1148 return Self::MIN;
1149 }
1150
1151 // Safety: `nanoseconds` is guaranteed to be in range because of to the modulus above.
1152 unsafe { Self::new_unchecked(seconds, nanoseconds) }
1153 }
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 pub fn time_fn<T>(f: impl FnOnce() -> T) -> (Self, T) {
1165 let start = Instant::now();
1166 let return_value = f();
1167 let end = Instant::now();
1168
1169 (end - start, return_value)
1170 }
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.
1187impl fmt::Display for Duration {
1188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1189 if self.is_negative() {
1190 f.write_str("-")?;
1191 }
1192
1193 if let Some(_precision) = f.precision() {
1194 // Concise, rounded representation.
1195
1196 if self.is_zero() {
1197 // Write a zero value with the requested precision.
1198 return (0.).fmt(f).and_then(|_| f.write_str("s"));
1199 }
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 return value.fmt(f).and_then(|_| f.write_str($name));
1207 }
1208 };
1209 }
1210
1211 // Even if this produces a de-normal float, because we're rounding we don't really care.
1212 let seconds = self.unsigned_abs().as_secs_f64();
1213
1214 item!("d", seconds / Second::per_t::<f64>(Day));
1215 item!("h", seconds / Second::per_t::<f64>(Hour));
1216 item!("m", seconds / Second::per_t::<f64>(Minute));
1217 item!("s", seconds);
1218 item!("ms", seconds * Millisecond::per_t::<f64>(Second));
1219 item!("µs", seconds * Microsecond::per_t::<f64>(Second));
1220 item!("ns", seconds * Nanosecond::per_t::<f64>(Second));
1221 } else {
1222 // Precise, but verbose representation.
1223
1224 if self.is_zero() {
1225 return f.write_str("0s");
1226 }
1227
1228 /// Format a single item.
1229 macro_rules! item {
1230 ($name:literal, $value:expr) => {
1231 match $value {
1232 0 => Ok(()),
1233 value => value.fmt(f).and_then(|_| f.write_str($name)),
1234 }
1235 };
1236 }
1237
1238 let seconds = self.seconds.unsigned_abs();
1239 let nanoseconds = self.nanoseconds.get().unsigned_abs();
1240
1241 item!("d", seconds / Second::per_t::<u64>(Day))?;
1242 item!(
1243 "h",
1244 seconds / Second::per_t::<u64>(Hour) % Hour::per_t::<u64>(Day)
1245 )?;
1246 item!(
1247 "m",
1248 seconds / Second::per_t::<u64>(Minute) % Minute::per_t::<u64>(Hour)
1249 )?;
1250 item!("s", seconds % Second::per_t::<u64>(Minute))?;
1251 item!("ms", nanoseconds / Nanosecond::per_t::<u32>(Millisecond))?;
1252 item!(
1253 "µs",
1254 nanoseconds / Nanosecond::per_t::<u32>(Microsecond)
1255 % Microsecond::per_t::<u32>(Millisecond)
1256 )?;
1257 item!("ns", nanoseconds % Nanosecond::per_t::<u32>(Microsecond))?;
1258 }
1259
1260 Ok(())
1261 }
1262}
1263
1264impl TryFrom<StdDuration> for Duration {
1265 type Error = error::ConversionRange;
1266
1267 fn try_from(original: StdDuration) -> Result<Self, error::ConversionRange> {
1268 Ok(Self::new(
1269 original
1270 .as_secs()
1271 .try_into()
1272 .map_err(|_| error::ConversionRange)?,
1273 original.subsec_nanos().cast_signed(),
1274 ))
1275 }
1276}
1277
1278impl TryFrom<Duration> for StdDuration {
1279 type Error = error::ConversionRange;
1280
1281 fn try_from(duration: Duration) -> Result<Self, error::ConversionRange> {
1282 Ok(Self::new(
1283 duration
1284 .seconds
1285 .try_into()
1286 .map_err(|_| error::ConversionRange)?,
1287 duration
1288 .nanoseconds
1289 .get()
1290 .try_into()
1291 .map_err(|_| error::ConversionRange)?,
1292 ))
1293 }
1294}
1295
1296impl Add for Duration {
1297 type Output = Self;
1298
1299 /// # Panics
1300 ///
1301 /// This may panic if an overflow occurs.
1302 fn add(self, rhs: Self) -> Self::Output {
1303 self.checked_add(rhs)
1304 .expect("overflow when adding durations")
1305 }
1306}
1307
1308impl Add<StdDuration> for Duration {
1309 type Output = Self;
1310
1311 /// # Panics
1312 ///
1313 /// This may panic if an overflow occurs.
1314 fn add(self, std_duration: StdDuration) -> Self::Output {
1315 self + Self::try_from(std_duration)
1316 .expect("overflow converting `std::time::Duration` to `time::Duration`")
1317 }
1318}
1319
1320impl Add<Duration> for StdDuration {
1321 type Output = Duration;
1322
1323 fn add(self, rhs: Duration) -> Self::Output {
1324 rhs + self
1325 }
1326}
1327
1328impl_add_assign!(Duration: Self, StdDuration);
1329
1330impl AddAssign<Duration> for StdDuration {
1331 /// # Panics
1332 ///
1333 /// This may panic if the resulting addition cannot be represented.
1334 fn add_assign(&mut self, rhs: Duration) {
1335 *self = (*self + rhs).try_into().expect(
1336 "Cannot represent a resulting duration in std. Try `let x = x + rhs;`, which will \
1337 change the type.",
1338 );
1339 }
1340}
1341
1342impl Neg for Duration {
1343 type Output = Self;
1344
1345 fn neg(self) -> Self::Output {
1346 self.checked_neg().expect("overflow when negating duration")
1347 }
1348}
1349
1350impl Sub for Duration {
1351 type Output = Self;
1352
1353 /// # Panics
1354 ///
1355 /// This may panic if an overflow occurs.
1356 fn sub(self, rhs: Self) -> Self::Output {
1357 self.checked_sub(rhs)
1358 .expect("overflow when subtracting durations")
1359 }
1360}
1361
1362impl Sub<StdDuration> for Duration {
1363 type Output = Self;
1364
1365 /// # Panics
1366 ///
1367 /// This may panic if an overflow occurs.
1368 fn sub(self, rhs: StdDuration) -> Self::Output {
1369 self - Self::try_from(rhs)
1370 .expect("overflow converting `std::time::Duration` to `time::Duration`")
1371 }
1372}
1373
1374impl Sub<Duration> for StdDuration {
1375 type Output = Duration;
1376
1377 /// # Panics
1378 ///
1379 /// This may panic if an overflow occurs.
1380 fn sub(self, rhs: Duration) -> Self::Output {
1381 Duration::try_from(self)
1382 .expect("overflow converting `std::time::Duration` to `time::Duration`")
1383 - rhs
1384 }
1385}
1386
1387impl_sub_assign!(Duration: Self, StdDuration);
1388
1389impl SubAssign<Duration> for StdDuration {
1390 /// # Panics
1391 ///
1392 /// This may panic if the resulting subtraction can not be represented.
1393 fn sub_assign(&mut self, rhs: Duration) {
1394 *self = (*self - rhs).try_into().expect(
1395 "Cannot represent a resulting duration in std. Try `let x = x - rhs;`, which will \
1396 change the type.",
1397 );
1398 }
1399}
1400
1401/// Implement `Mul` (reflexively) and `Div` for `Duration` for various types.
1402macro_rules! duration_mul_div_int {
1403 ($($type:ty),+) => {$(
1404 impl Mul<$type> for Duration {
1405 type Output = Self;
1406
1407 fn mul(self, rhs: $type) -> Self::Output {
1408 Self::nanoseconds_i128(
1409 self.whole_nanoseconds()
1410 .checked_mul(rhs.cast_signed().extend::<i128>())
1411 .expect("overflow when multiplying duration")
1412 )
1413 }
1414 }
1415
1416 impl Mul<Duration> for $type {
1417 type Output = Duration;
1418
1419 fn mul(self, rhs: Duration) -> Self::Output {
1420 rhs * self
1421 }
1422 }
1423
1424 impl Div<$type> for Duration {
1425 type Output = Self;
1426
1427 fn div(self, rhs: $type) -> Self::Output {
1428 Self::nanoseconds_i128(
1429 self.whole_nanoseconds() / rhs.cast_signed().extend::<i128>()
1430 )
1431 }
1432 }
1433 )+};
1434}
1435duration_mul_div_int![i8, i16, i32, u8, u16, u32];
1436
1437impl Mul<f32> for Duration {
1438 type Output = Self;
1439
1440 fn mul(self, rhs: f32) -> Self::Output {
1441 Self::seconds_f32(self.as_seconds_f32() * rhs)
1442 }
1443}
1444
1445impl Mul<Duration> for f32 {
1446 type Output = Duration;
1447
1448 fn mul(self, rhs: Duration) -> Self::Output {
1449 rhs * self
1450 }
1451}
1452
1453impl Mul<f64> for Duration {
1454 type Output = Self;
1455
1456 fn mul(self, rhs: f64) -> Self::Output {
1457 Self::seconds_f64(self.as_seconds_f64() * rhs)
1458 }
1459}
1460
1461impl Mul<Duration> for f64 {
1462 type Output = Duration;
1463
1464 fn mul(self, rhs: Duration) -> Self::Output {
1465 rhs * self
1466 }
1467}
1468
1469impl_mul_assign!(Duration: i8, i16, i32, u8, u16, u32, f32, f64);
1470
1471impl Div<f32> for Duration {
1472 type Output = Self;
1473
1474 fn div(self, rhs: f32) -> Self::Output {
1475 Self::seconds_f32(self.as_seconds_f32() / rhs)
1476 }
1477}
1478
1479impl Div<f64> for Duration {
1480 type Output = Self;
1481
1482 fn div(self, rhs: f64) -> Self::Output {
1483 Self::seconds_f64(self.as_seconds_f64() / rhs)
1484 }
1485}
1486
1487impl_div_assign!(Duration: i8, i16, i32, u8, u16, u32, f32, f64);
1488
1489impl Div for Duration {
1490 type Output = f64;
1491
1492 fn div(self, rhs: Self) -> Self::Output {
1493 self.as_seconds_f64() / rhs.as_seconds_f64()
1494 }
1495}
1496
1497impl Div<StdDuration> for Duration {
1498 type Output = f64;
1499
1500 fn div(self, rhs: StdDuration) -> Self::Output {
1501 self.as_seconds_f64() / rhs.as_secs_f64()
1502 }
1503}
1504
1505impl Div<Duration> for StdDuration {
1506 type Output = f64;
1507
1508 fn div(self, rhs: Duration) -> Self::Output {
1509 self.as_secs_f64() / rhs.as_seconds_f64()
1510 }
1511}
1512
1513impl PartialEq<StdDuration> for Duration {
1514 fn eq(&self, rhs: &StdDuration) -> bool {
1515 Ok(*self) == Self::try_from(*rhs)
1516 }
1517}
1518
1519impl PartialEq<Duration> for StdDuration {
1520 fn eq(&self, rhs: &Duration) -> bool {
1521 rhs == self
1522 }
1523}
1524
1525impl PartialOrd<StdDuration> for Duration {
1526 fn partial_cmp(&self, rhs: &StdDuration) -> Option<Ordering> {
1527 if rhs.as_secs() > i64::MAX.cast_unsigned() {
1528 return Some(Ordering::Less);
1529 }
1530
1531 Some(
1532 self.seconds
1533 .cmp(&rhs.as_secs().cast_signed())
1534 .then_with(|| {
1535 self.nanoseconds
1536 .get()
1537 .cmp(&rhs.subsec_nanos().cast_signed())
1538 }),
1539 )
1540 }
1541}
1542
1543impl PartialOrd<Duration> for StdDuration {
1544 fn partial_cmp(&self, rhs: &Duration) -> Option<Ordering> {
1545 rhs.partial_cmp(self).map(Ordering::reverse)
1546 }
1547}
1548
1549impl Sum for Duration {
1550 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
1551 iter.reduce(|a, b| a + b).unwrap_or_default()
1552 }
1553}
1554
1555impl<'a> Sum<&'a Self> for Duration {
1556 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
1557 iter.copied().sum()
1558 }
1559}
1560
1561#[cfg(feature = "std")]
1562impl Add<Duration> for SystemTime {
1563 type Output = Self;
1564
1565 fn add(self, duration: Duration) -> Self::Output {
1566 if duration.is_zero() {
1567 self
1568 } else if duration.is_positive() {
1569 self + duration.unsigned_abs()
1570 } else {
1571 debug_assert!(duration.is_negative());
1572 self - duration.unsigned_abs()
1573 }
1574 }
1575}
1576
1577impl_add_assign!(SystemTime: #[cfg(feature = "std")] Duration);
1578
1579#[cfg(feature = "std")]
1580impl Sub<Duration> for SystemTime {
1581 type Output = Self;
1582
1583 fn sub(self, duration: Duration) -> Self::Output {
1584 if duration.is_zero() {
1585 self
1586 } else if duration.is_positive() {
1587 self - duration.unsigned_abs()
1588 } else {
1589 debug_assert!(duration.is_negative());
1590 self + duration.unsigned_abs()
1591 }
1592 }
1593}
1594
1595impl_sub_assign!(SystemTime: #[cfg(feature = "std")] Duration);