summaryrefslogtreecommitdiffstats
path: root/vendor/time/src/duration.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/time/src/duration.rs')
-rw-r--r--vendor/time/src/duration.rs442
1 files changed, 356 insertions, 86 deletions
diff --git a/vendor/time/src/duration.rs b/vendor/time/src/duration.rs
index 47c3f1516..453d2254d 100644
--- a/vendor/time/src/duration.rs
+++ b/vendor/time/src/duration.rs
@@ -6,6 +6,7 @@ use core::iter::Sum;
use core::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
use core::time::Duration as StdDuration;
+use crate::convert::*;
use crate::error;
#[cfg(feature = "std")]
use crate::Instant;
@@ -50,6 +51,124 @@ impl fmt::Debug for Duration {
}
}
+/// This is adapted from the `std` implementation, which uses mostly bit
+/// operations to ensure the highest precision:
+/// https://github.com/rust-lang/rust/blob/3a37c2f0523c87147b64f1b8099fc9df22e8c53e/library/core/src/time.rs#L1262-L1340
+/// Changes from `std` are marked and explained below.
+#[rustfmt::skip] // Skip `rustfmt` because it reformats the arguments of the macro weirdly.
+macro_rules! try_from_secs {
+ (
+ secs = $secs: expr,
+ mantissa_bits = $mant_bits: literal,
+ exponent_bits = $exp_bits: literal,
+ offset = $offset: literal,
+ bits_ty = $bits_ty:ty,
+ bits_ty_signed = $bits_ty_signed:ty,
+ double_ty = $double_ty:ty,
+ float_ty = $float_ty:ty,
+ is_nan = $is_nan:expr,
+ is_overflow = $is_overflow:expr,
+ ) => {{
+ 'value: {
+ const MIN_EXP: i16 = 1 - (1i16 << $exp_bits) / 2;
+ const MANT_MASK: $bits_ty = (1 << $mant_bits) - 1;
+ const EXP_MASK: $bits_ty = (1 << $exp_bits) - 1;
+
+ // Change from std: No error check for negative values necessary.
+
+ let bits = $secs.to_bits();
+ let mant = (bits & MANT_MASK) | (MANT_MASK + 1);
+ let exp = ((bits >> $mant_bits) & EXP_MASK) as i16 + MIN_EXP;
+
+ let (secs, nanos) = if exp < -31 {
+ // the input represents less than 1ns and can not be rounded to it
+ (0u64, 0u32)
+ } else if exp < 0 {
+ // the input is less than 1 second
+ let t = <$double_ty>::from(mant) << ($offset + exp);
+ let nanos_offset = $mant_bits + $offset;
+ let nanos_tmp = u128::from(Nanosecond.per(Second)) * u128::from(t);
+ let nanos = (nanos_tmp >> nanos_offset) as u32;
+
+ let rem_mask = (1 << nanos_offset) - 1;
+ let rem_msb_mask = 1 << (nanos_offset - 1);
+ let rem = nanos_tmp & rem_mask;
+ let is_tie = rem == rem_msb_mask;
+ let is_even = (nanos & 1) == 0;
+ let rem_msb = nanos_tmp & rem_msb_mask == 0;
+ let add_ns = !(rem_msb || (is_even && is_tie));
+
+ // f32 does not have enough precision to trigger the second branch
+ // since it can not represent numbers between 0.999_999_940_395 and 1.0.
+ let nanos = nanos + add_ns as u32;
+ if ($mant_bits == 23) || (nanos != Nanosecond.per(Second)) {
+ (0, nanos)
+ } else {
+ (1, 0)
+ }
+ } else if exp < $mant_bits {
+ let secs = u64::from(mant >> ($mant_bits - exp));
+ let t = <$double_ty>::from((mant << exp) & MANT_MASK);
+ let nanos_offset = $mant_bits;
+ let nanos_tmp = <$double_ty>::from(Nanosecond.per(Second)) * t;
+ let nanos = (nanos_tmp >> nanos_offset) as u32;
+
+ let rem_mask = (1 << nanos_offset) - 1;
+ let rem_msb_mask = 1 << (nanos_offset - 1);
+ let rem = nanos_tmp & rem_mask;
+ let is_tie = rem == rem_msb_mask;
+ let is_even = (nanos & 1) == 0;
+ let rem_msb = nanos_tmp & rem_msb_mask == 0;
+ let add_ns = !(rem_msb || (is_even && is_tie));
+
+ // f32 does not have enough precision to trigger the second branch.
+ // For example, it can not represent numbers between 1.999_999_880...
+ // and 2.0. Bigger values result in even smaller precision of the
+ // fractional part.
+ let nanos = nanos + add_ns as u32;
+ if ($mant_bits == 23) || (nanos != Nanosecond.per(Second)) {
+ (secs, nanos)
+ } else {
+ (secs + 1, 0)
+ }
+ } else if exp < 63 {
+ // Change from std: The exponent here is 63 instead of 64,
+ // because i64::MAX + 1 is 2^63.
+
+ // the input has no fractional part
+ let secs = u64::from(mant) << (exp - $mant_bits);
+ (secs, 0)
+ } else if bits == (i64::MIN as $float_ty).to_bits() {
+ // Change from std: Signed integers are asymmetrical in that
+ // iN::MIN is -iN::MAX - 1. So for example i8 covers the
+ // following numbers -128..=127. The check above (exp < 63)
+ // doesn't cover i64::MIN as that is -2^63, so we have this
+ // additional case to handle the asymmetry of iN::MIN.
+ break 'value Self::new_unchecked(i64::MIN, 0);
+ } else if $secs.is_nan() {
+ // Change from std: std doesn't differentiate between the error
+ // cases.
+ $is_nan
+ } else {
+ $is_overflow
+ };
+
+ // Change from std: All the code is mostly unmodified in that it
+ // simply calculates an unsigned integer. Here we extract the sign
+ // bit and assign it to the number. We basically manually do two's
+ // complement here, we could also use an if and just negate the
+ // numbers based on the sign, but it turns out to be quite a bit
+ // slower.
+ let mask = (bits as $bits_ty_signed) >> ($mant_bits + $exp_bits);
+ #[allow(trivial_numeric_casts)]
+ let secs_signed = ((secs as i64) ^ (mask as i64)) - (mask as i64);
+ #[allow(trivial_numeric_casts)]
+ let nanos_signed = ((nanos as i32) ^ (mask as i32)) - (mask as i32);
+ Self::new_unchecked(secs_signed, nanos_signed)
+ }
+ }};
+}
+
impl Duration {
// region: constants
/// Equivalent to `0.seconds()`.
@@ -125,10 +244,10 @@ impl Duration {
pub const WEEK: Self = Self::weeks(1);
/// The minimum possible duration. Adding any negative duration to this will cause an overflow.
- pub const MIN: Self = Self::new_unchecked(i64::MIN, -999_999_999);
+ pub const MIN: Self = Self::new_unchecked(i64::MIN, -((Nanosecond.per(Second) - 1) as i32));
/// The maximum possible duration. Adding any positive duration to this will cause an overflow.
- pub const MAX: Self = Self::new_unchecked(i64::MAX, 999_999_999);
+ pub const MAX: Self = Self::new_unchecked(i64::MAX, (Nanosecond.per(Second) - 1) as _);
// endregion constants
// region: is_{sign}
@@ -202,12 +321,12 @@ impl Duration {
pub(crate) const fn new_unchecked(seconds: i64, nanoseconds: i32) -> Self {
if seconds < 0 {
debug_assert!(nanoseconds <= 0);
- debug_assert!(nanoseconds > -1_000_000_000);
+ debug_assert!(nanoseconds > -(Nanosecond.per(Second) as i32));
} else if seconds > 0 {
debug_assert!(nanoseconds >= 0);
- debug_assert!(nanoseconds < 1_000_000_000);
+ debug_assert!(nanoseconds < Nanosecond.per(Second) as _);
} else {
- debug_assert!(nanoseconds.unsigned_abs() < 1_000_000_000);
+ debug_assert!(nanoseconds.unsigned_abs() < Nanosecond.per(Second));
}
Self {
@@ -228,19 +347,19 @@ impl Duration {
/// ```
pub const fn new(mut seconds: i64, mut nanoseconds: i32) -> Self {
seconds = expect_opt!(
- seconds.checked_add(nanoseconds as i64 / 1_000_000_000),
+ seconds.checked_add(nanoseconds as i64 / Nanosecond.per(Second) as i64),
"overflow constructing `time::Duration`"
);
- nanoseconds %= 1_000_000_000;
+ nanoseconds %= Nanosecond.per(Second) as i32;
if seconds > 0 && nanoseconds < 0 {
// `seconds` cannot overflow here because it is positive.
seconds -= 1;
- nanoseconds += 1_000_000_000;
+ nanoseconds += Nanosecond.per(Second) as i32;
} else if seconds < 0 && nanoseconds > 0 {
// `seconds` cannot overflow here because it is negative.
seconds += 1;
- nanoseconds -= 1_000_000_000;
+ nanoseconds -= Nanosecond.per(Second) as i32;
}
Self::new_unchecked(seconds, nanoseconds)
@@ -255,7 +374,7 @@ impl Duration {
/// ```
pub const fn weeks(weeks: i64) -> Self {
Self::seconds(expect_opt!(
- weeks.checked_mul(604_800),
+ weeks.checked_mul(Second.per(Week) as _),
"overflow constructing `time::Duration`"
))
}
@@ -269,7 +388,7 @@ impl Duration {
/// ```
pub const fn days(days: i64) -> Self {
Self::seconds(expect_opt!(
- days.checked_mul(86_400),
+ days.checked_mul(Second.per(Day) as _),
"overflow constructing `time::Duration`"
))
}
@@ -283,7 +402,7 @@ impl Duration {
/// ```
pub const fn hours(hours: i64) -> Self {
Self::seconds(expect_opt!(
- hours.checked_mul(3_600),
+ hours.checked_mul(Second.per(Hour) as _),
"overflow constructing `time::Duration`"
))
}
@@ -297,7 +416,7 @@ impl Duration {
/// ```
pub const fn minutes(minutes: i64) -> Self {
Self::seconds(expect_opt!(
- minutes.checked_mul(60),
+ minutes.checked_mul(Second.per(Minute) as _),
"overflow constructing `time::Duration`"
))
}
@@ -320,16 +439,18 @@ impl Duration {
/// assert_eq!(Duration::seconds_f64(-0.5), -0.5.seconds());
/// ```
pub fn seconds_f64(seconds: f64) -> Self {
- if seconds > i64::MAX as f64 || seconds < i64::MIN as f64 {
- crate::expect_failed("overflow constructing `time::Duration`");
- }
- if seconds.is_nan() {
- crate::expect_failed("passed NaN to `time::Duration::seconds_f64`");
- }
- let seconds_truncated = seconds as i64;
- // This only works because we handle the overflow condition above.
- let nanoseconds = ((seconds - seconds_truncated as f64) * 1_000_000_000.) as i32;
- Self::new_unchecked(seconds_truncated, nanoseconds)
+ try_from_secs!(
+ secs = seconds,
+ mantissa_bits = 52,
+ exponent_bits = 11,
+ offset = 44,
+ bits_ty = u64,
+ bits_ty_signed = i64,
+ double_ty = u128,
+ float_ty = f64,
+ is_nan = crate::expect_failed("passed NaN to `time::Duration::seconds_f64`"),
+ is_overflow = crate::expect_failed("overflow constructing `time::Duration`"),
+ )
}
/// Creates a new `Duration` from the specified number of seconds represented as `f32`.
@@ -340,16 +461,146 @@ impl Duration {
/// assert_eq!(Duration::seconds_f32(-0.5), (-0.5).seconds());
/// ```
pub fn seconds_f32(seconds: f32) -> Self {
- if seconds > i64::MAX as f32 || seconds < i64::MIN as f32 {
- crate::expect_failed("overflow constructing `time::Duration`");
- }
- if seconds.is_nan() {
- crate::expect_failed("passed NaN to `time::Duration::seconds_f32`");
- }
- let seconds_truncated = seconds as i64;
- // This only works because we handle the overflow condition above.
- let nanoseconds = ((seconds - seconds_truncated as f32) * 1_000_000_000.) as i32;
- Self::new_unchecked(seconds_truncated, nanoseconds)
+ try_from_secs!(
+ secs = seconds,
+ mantissa_bits = 23,
+ exponent_bits = 8,
+ offset = 41,
+ bits_ty = u32,
+ bits_ty_signed = i32,
+ double_ty = u64,
+ float_ty = f32,
+ is_nan = crate::expect_failed("passed NaN to `time::Duration::seconds_f32`"),
+ is_overflow = crate::expect_failed("overflow constructing `time::Duration`"),
+ )
+ }
+
+ /// Creates a new `Duration` from the specified number of seconds
+ /// represented as `f64`. Any values that are out of bounds are saturated at
+ /// the minimum or maximum respectively. `NaN` gets turned into a `Duration`
+ /// of 0 seconds.
+ ///
+ /// ```rust
+ /// # use time::{Duration, ext::NumericalDuration};
+ /// assert_eq!(Duration::saturating_seconds_f64(0.5), 0.5.seconds());
+ /// assert_eq!(Duration::saturating_seconds_f64(-0.5), -0.5.seconds());
+ /// assert_eq!(
+ /// Duration::saturating_seconds_f64(f64::NAN),
+ /// Duration::new(0, 0),
+ /// );
+ /// assert_eq!(
+ /// Duration::saturating_seconds_f64(f64::NEG_INFINITY),
+ /// Duration::MIN,
+ /// );
+ /// assert_eq!(
+ /// Duration::saturating_seconds_f64(f64::INFINITY),
+ /// Duration::MAX,
+ /// );
+ /// ```
+ pub fn saturating_seconds_f64(seconds: f64) -> Self {
+ try_from_secs!(
+ secs = seconds,
+ mantissa_bits = 52,
+ exponent_bits = 11,
+ offset = 44,
+ bits_ty = u64,
+ bits_ty_signed = i64,
+ double_ty = u128,
+ float_ty = f64,
+ is_nan = return Self::ZERO,
+ is_overflow = return if seconds < 0.0 { Self::MIN } else { Self::MAX },
+ )
+ }
+
+ /// Creates a new `Duration` from the specified number of seconds
+ /// represented as `f32`. Any values that are out of bounds are saturated at
+ /// the minimum or maximum respectively. `NaN` gets turned into a `Duration`
+ /// of 0 seconds.
+ ///
+ /// ```rust
+ /// # use time::{Duration, ext::NumericalDuration};
+ /// assert_eq!(Duration::saturating_seconds_f32(0.5), 0.5.seconds());
+ /// assert_eq!(Duration::saturating_seconds_f32(-0.5), (-0.5).seconds());
+ /// assert_eq!(
+ /// Duration::saturating_seconds_f32(f32::NAN),
+ /// Duration::new(0, 0),
+ /// );
+ /// assert_eq!(
+ /// Duration::saturating_seconds_f32(f32::NEG_INFINITY),
+ /// Duration::MIN,
+ /// );
+ /// assert_eq!(
+ /// Duration::saturating_seconds_f32(f32::INFINITY),
+ /// Duration::MAX,
+ /// );
+ /// ```
+ pub fn saturating_seconds_f32(seconds: f32) -> Self {
+ try_from_secs!(
+ secs = seconds,
+ mantissa_bits = 23,
+ exponent_bits = 8,
+ offset = 41,
+ bits_ty = u32,
+ bits_ty_signed = i32,
+ double_ty = u64,
+ float_ty = f32,
+ is_nan = return Self::ZERO,
+ is_overflow = return if seconds < 0.0 { Self::MIN } else { Self::MAX },
+ )
+ }
+
+ /// Creates a new `Duration` from the specified number of seconds
+ /// represented as `f64`. Returns `None` if the `Duration` can't be
+ /// represented.
+ ///
+ /// ```rust
+ /// # use time::{Duration, ext::NumericalDuration};
+ /// assert_eq!(Duration::checked_seconds_f64(0.5), Some(0.5.seconds()));
+ /// assert_eq!(Duration::checked_seconds_f64(-0.5), Some(-0.5.seconds()));
+ /// assert_eq!(Duration::checked_seconds_f64(f64::NAN), None);
+ /// assert_eq!(Duration::checked_seconds_f64(f64::NEG_INFINITY), None);
+ /// assert_eq!(Duration::checked_seconds_f64(f64::INFINITY), None);
+ /// ```
+ pub fn checked_seconds_f64(seconds: f64) -> Option<Self> {
+ Some(try_from_secs!(
+ secs = seconds,
+ mantissa_bits = 52,
+ exponent_bits = 11,
+ offset = 44,
+ bits_ty = u64,
+ bits_ty_signed = i64,
+ double_ty = u128,
+ float_ty = f64,
+ is_nan = return None,
+ is_overflow = return None,
+ ))
+ }
+
+ /// Creates a new `Duration` from the specified number of seconds
+ /// represented as `f32`. Returns `None` if the `Duration` can't be
+ /// represented.
+ ///
+ /// ```rust
+ /// # use time::{Duration, ext::NumericalDuration};
+ /// assert_eq!(Duration::checked_seconds_f32(0.5), Some(0.5.seconds()));
+ /// assert_eq!(Duration::checked_seconds_f32(-0.5), Some(-0.5.seconds()));
+ /// assert_eq!(Duration::checked_seconds_f32(f32::NAN), None);
+ /// assert_eq!(Duration::checked_seconds_f32(f32::NEG_INFINITY), None);
+ /// assert_eq!(Duration::checked_seconds_f32(f32::INFINITY), None);
+ /// ```
+ pub fn checked_seconds_f32(seconds: f32) -> Option<Self> {
+ Some(try_from_secs!(
+ secs = seconds,
+ mantissa_bits = 23,
+ exponent_bits = 8,
+ offset = 41,
+ bits_ty = u32,
+ bits_ty_signed = i32,
+ double_ty = u64,
+ float_ty = f32,
+ is_nan = return None,
+ is_overflow = return None,
+ ))
}
/// Create a new `Duration` with the given number of milliseconds.
@@ -361,8 +612,9 @@ impl Duration {
/// ```
pub const fn milliseconds(milliseconds: i64) -> Self {
Self::new_unchecked(
- milliseconds / 1_000,
- ((milliseconds % 1_000) * 1_000_000) as _,
+ milliseconds / Millisecond.per(Second) as i64,
+ (milliseconds % Millisecond.per(Second) as i64 * Nanosecond.per(Millisecond) as i64)
+ as _,
)
}
@@ -375,8 +627,9 @@ impl Duration {
/// ```
pub const fn microseconds(microseconds: i64) -> Self {
Self::new_unchecked(
- microseconds / 1_000_000,
- ((microseconds % 1_000_000) * 1_000) as _,
+ microseconds / Microsecond.per(Second) as i64,
+ (microseconds % Microsecond.per(Second) as i64 * Nanosecond.per(Microsecond) as i64)
+ as _,
)
}
@@ -389,8 +642,8 @@ impl Duration {
/// ```
pub const fn nanoseconds(nanoseconds: i64) -> Self {
Self::new_unchecked(
- nanoseconds / 1_000_000_000,
- (nanoseconds % 1_000_000_000) as _,
+ nanoseconds / Nanosecond.per(Second) as i64,
+ (nanoseconds % Nanosecond.per(Second) as i64) as _,
)
}
@@ -399,8 +652,8 @@ impl Duration {
/// As the input range cannot be fully mapped to the output, this should only be used where it's
/// known to result in a valid value.
pub(crate) const fn nanoseconds_i128(nanoseconds: i128) -> Self {
- let seconds = nanoseconds / 1_000_000_000;
- let nanoseconds = nanoseconds % 1_000_000_000;
+ let seconds = nanoseconds / Nanosecond.per(Second) as i128;
+ let nanoseconds = nanoseconds % Nanosecond.per(Second) as i128;
if seconds > i64::MAX as i128 || seconds < i64::MIN as i128 {
crate::expect_failed("overflow constructing `time::Duration`");
@@ -421,7 +674,7 @@ impl Duration {
/// assert_eq!((-6).days().whole_weeks(), 0);
/// ```
pub const fn whole_weeks(self) -> i64 {
- self.whole_seconds() / 604_800
+ self.whole_seconds() / Second.per(Week) as i64
}
/// Get the number of whole days in the duration.
@@ -434,7 +687,7 @@ impl Duration {
/// assert_eq!((-23).hours().whole_days(), 0);
/// ```
pub const fn whole_days(self) -> i64 {
- self.whole_seconds() / 86_400
+ self.whole_seconds() / Second.per(Day) as i64
}
/// Get the number of whole hours in the duration.
@@ -447,7 +700,7 @@ impl Duration {
/// assert_eq!((-59).minutes().whole_hours(), 0);
/// ```
pub const fn whole_hours(self) -> i64 {
- self.whole_seconds() / 3_600
+ self.whole_seconds() / Second.per(Hour) as i64
}
/// Get the number of whole minutes in the duration.
@@ -460,7 +713,7 @@ impl Duration {
/// assert_eq!((-59).seconds().whole_minutes(), 0);
/// ```
pub const fn whole_minutes(self) -> i64 {
- self.whole_seconds() / 60
+ self.whole_seconds() / Second.per(Minute) as i64
}
/// Get the number of whole seconds in the duration.
@@ -484,7 +737,7 @@ impl Duration {
/// assert_eq!((-1.5).seconds().as_seconds_f64(), -1.5);
/// ```
pub fn as_seconds_f64(self) -> f64 {
- self.seconds as f64 + self.nanoseconds as f64 / 1_000_000_000.
+ self.seconds as f64 + self.nanoseconds as f64 / Nanosecond.per(Second) as f64
}
/// Get the number of fractional seconds in the duration.
@@ -495,7 +748,7 @@ impl Duration {
/// assert_eq!((-1.5).seconds().as_seconds_f32(), -1.5);
/// ```
pub fn as_seconds_f32(self) -> f32 {
- self.seconds as f32 + self.nanoseconds as f32 / 1_000_000_000.
+ self.seconds as f32 + self.nanoseconds as f32 / Nanosecond.per(Second) as f32
}
/// Get the number of whole milliseconds in the duration.
@@ -508,7 +761,8 @@ impl Duration {
/// assert_eq!((-1).milliseconds().whole_milliseconds(), -1);
/// ```
pub const fn whole_milliseconds(self) -> i128 {
- self.seconds as i128 * 1_000 + self.nanoseconds as i128 / 1_000_000
+ self.seconds as i128 * Millisecond.per(Second) as i128
+ + self.nanoseconds as i128 / Nanosecond.per(Millisecond) as i128
}
/// Get the number of milliseconds past the number of whole seconds.
@@ -522,7 +776,7 @@ impl Duration {
/// ```
// Allow the lint, as the value is guaranteed to be less than 1000.
pub const fn subsec_milliseconds(self) -> i16 {
- (self.nanoseconds / 1_000_000) as _
+ (self.nanoseconds / Nanosecond.per(Millisecond) as i32) as _
}
/// Get the number of whole microseconds in the duration.
@@ -535,7 +789,8 @@ impl Duration {
/// assert_eq!((-1).microseconds().whole_microseconds(), -1);
/// ```
pub const fn whole_microseconds(self) -> i128 {
- self.seconds as i128 * 1_000_000 + self.nanoseconds as i128 / 1_000
+ self.seconds as i128 * Microsecond.per(Second) as i128
+ + self.nanoseconds as i128 / Nanosecond.per(Microsecond) as i128
}
/// Get the number of microseconds past the number of whole seconds.
@@ -548,7 +803,7 @@ impl Duration {
/// assert_eq!((-1.0004).seconds().subsec_microseconds(), -400);
/// ```
pub const fn subsec_microseconds(self) -> i32 {
- self.nanoseconds / 1_000
+ self.nanoseconds / Nanosecond.per(Microsecond) as i32
}
/// Get the number of nanoseconds in the duration.
@@ -561,7 +816,7 @@ impl Duration {
/// assert_eq!((-1).nanoseconds().whole_nanoseconds(), -1);
/// ```
pub const fn whole_nanoseconds(self) -> i128 {
- self.seconds as i128 * 1_000_000_000 + self.nanoseconds as i128
+ self.seconds as i128 * Nanosecond.per(Second) as i128 + self.nanoseconds as i128
}
/// Get the number of nanoseconds past the number of whole seconds.
@@ -591,11 +846,12 @@ impl Duration {
let mut seconds = const_try_opt!(self.seconds.checked_add(rhs.seconds));
let mut nanoseconds = self.nanoseconds + rhs.nanoseconds;
- if nanoseconds >= 1_000_000_000 || seconds < 0 && nanoseconds > 0 {
- nanoseconds -= 1_000_000_000;
+ if nanoseconds >= Nanosecond.per(Second) as _ || seconds < 0 && nanoseconds > 0 {
+ nanoseconds -= Nanosecond.per(Second) as i32;
seconds = const_try_opt!(seconds.checked_add(1));
- } else if nanoseconds <= -1_000_000_000 || seconds > 0 && nanoseconds < 0 {
- nanoseconds += 1_000_000_000;
+ } else if nanoseconds <= -(Nanosecond.per(Second) as i32) || seconds > 0 && nanoseconds < 0
+ {
+ nanoseconds += Nanosecond.per(Second) as i32;
seconds = const_try_opt!(seconds.checked_sub(1));
}
@@ -614,11 +870,12 @@ impl Duration {
let mut seconds = const_try_opt!(self.seconds.checked_sub(rhs.seconds));
let mut nanoseconds = self.nanoseconds - rhs.nanoseconds;
- if nanoseconds >= 1_000_000_000 || seconds < 0 && nanoseconds > 0 {
- nanoseconds -= 1_000_000_000;
+ if nanoseconds >= Nanosecond.per(Second) as _ || seconds < 0 && nanoseconds > 0 {
+ nanoseconds -= Nanosecond.per(Second) as i32;
seconds = const_try_opt!(seconds.checked_add(1));
- } else if nanoseconds <= -1_000_000_000 || seconds > 0 && nanoseconds < 0 {
- nanoseconds += 1_000_000_000;
+ } else if nanoseconds <= -(Nanosecond.per(Second) as i32) || seconds > 0 && nanoseconds < 0
+ {
+ nanoseconds += Nanosecond.per(Second) as i32;
seconds = const_try_opt!(seconds.checked_sub(1));
}
@@ -638,8 +895,8 @@ impl Duration {
pub const fn checked_mul(self, rhs: i32) -> Option<Self> {
// Multiply nanoseconds as i64, because it cannot overflow that way.
let total_nanos = self.nanoseconds as i64 * rhs as i64;
- let extra_secs = total_nanos / 1_000_000_000;
- let nanoseconds = (total_nanos % 1_000_000_000) as _;
+ let extra_secs = total_nanos / Nanosecond.per(Second) as i64;
+ let nanoseconds = (total_nanos % Nanosecond.per(Second) as i64) as _;
let seconds = const_try_opt!(
const_try_opt!(self.seconds.checked_mul(rhs as _)).checked_add(extra_secs)
);
@@ -658,7 +915,8 @@ impl Duration {
pub const fn checked_div(self, rhs: i32) -> Option<Self> {
let seconds = const_try_opt!(self.seconds.checked_div(rhs as i64));
let carry = self.seconds - seconds * (rhs as i64);
- let extra_nanos = const_try_opt!((carry * 1_000_000_000).checked_div(rhs as i64));
+ let extra_nanos =
+ const_try_opt!((carry * Nanosecond.per(Second) as i64).checked_div(rhs as i64));
let nanoseconds = const_try_opt!(self.nanoseconds.checked_div(rhs)) + (extra_nanos as i32);
Some(Self::new_unchecked(seconds, nanoseconds))
@@ -688,14 +946,15 @@ impl Duration {
}
let mut nanoseconds = self.nanoseconds + rhs.nanoseconds;
- if nanoseconds >= 1_000_000_000 || seconds < 0 && nanoseconds > 0 {
- nanoseconds -= 1_000_000_000;
+ if nanoseconds >= Nanosecond.per(Second) as _ || seconds < 0 && nanoseconds > 0 {
+ nanoseconds -= Nanosecond.per(Second) as i32;
seconds = match seconds.checked_add(1) {
Some(seconds) => seconds,
None => return Self::MAX,
};
- } else if nanoseconds <= -1_000_000_000 || seconds > 0 && nanoseconds < 0 {
- nanoseconds += 1_000_000_000;
+ } else if nanoseconds <= -(Nanosecond.per(Second) as i32) || seconds > 0 && nanoseconds < 0
+ {
+ nanoseconds += Nanosecond.per(Second) as i32;
seconds = match seconds.checked_sub(1) {
Some(seconds) => seconds,
None => return Self::MIN,
@@ -727,14 +986,15 @@ impl Duration {
}
let mut nanoseconds = self.nanoseconds - rhs.nanoseconds;
- if nanoseconds >= 1_000_000_000 || seconds < 0 && nanoseconds > 0 {
- nanoseconds -= 1_000_000_000;
+ if nanoseconds >= Nanosecond.per(Second) as _ || seconds < 0 && nanoseconds > 0 {
+ nanoseconds -= Nanosecond.per(Second) as i32;
seconds = match seconds.checked_add(1) {
Some(seconds) => seconds,
None => return Self::MAX,
};
- } else if nanoseconds <= -1_000_000_000 || seconds > 0 && nanoseconds < 0 {
- nanoseconds += 1_000_000_000;
+ } else if nanoseconds <= -(Nanosecond.per(Second) as i32) || seconds > 0 && nanoseconds < 0
+ {
+ nanoseconds += Nanosecond.per(Second) as i32;
seconds = match seconds.checked_sub(1) {
Some(seconds) => seconds,
None => return Self::MIN,
@@ -759,8 +1019,8 @@ impl Duration {
pub const fn saturating_mul(self, rhs: i32) -> Self {
// Multiply nanoseconds as i64, because it cannot overflow that way.
let total_nanos = self.nanoseconds as i64 * rhs as i64;
- let extra_secs = total_nanos / 1_000_000_000;
- let nanoseconds = (total_nanos % 1_000_000_000) as _;
+ let extra_secs = total_nanos / Nanosecond.per(Second) as i64;
+ let nanoseconds = (total_nanos % Nanosecond.per(Second) as i64) as _;
let (seconds, overflow1) = self.seconds.overflowing_mul(rhs as _);
if overflow1 {
if self.seconds > 0 && rhs > 0 || self.seconds < 0 && rhs < 0 {
@@ -834,13 +1094,13 @@ impl fmt::Display for Duration {
// Even if this produces a de-normal float, because we're rounding we don't really care.
let seconds = self.unsigned_abs().as_secs_f64();
- item!("d", seconds / 86_400.);
- item!("h", seconds / 3_600.);
- item!("m", seconds / 60.);
+ item!("d", seconds / Second.per(Day) as f64);
+ item!("h", seconds / Second.per(Hour) as f64);
+ item!("m", seconds / Second.per(Minute) as f64);
item!("s", seconds);
- item!("ms", seconds * 1_000.);
- item!("µs", seconds * 1_000_000.);
- item!("ns", seconds * 1_000_000_000.);
+ item!("ms", seconds * Millisecond.per(Second) as f64);
+ item!("µs", seconds * Microsecond.per(Second) as f64);
+ item!("ns", seconds * Nanosecond.per(Second) as f64);
} else {
// Precise, but verbose representation.
@@ -861,13 +1121,23 @@ impl fmt::Display for Duration {
let seconds = self.seconds.unsigned_abs();
let nanoseconds = self.nanoseconds.unsigned_abs();
- item!("d", seconds / 86_400)?;
- item!("h", seconds / 3_600 % 24)?;
- item!("m", seconds / 60 % 60)?;
- item!("s", seconds % 60)?;
- item!("ms", nanoseconds / 1_000_000)?;
- item!("µs", nanoseconds / 1_000 % 1_000)?;
- item!("ns", nanoseconds % 1_000)?;
+ item!("d", seconds / Second.per(Day) as u64)?;
+ item!(
+ "h",
+ seconds / Second.per(Hour) as u64 % Hour.per(Day) as u64
+ )?;
+ item!(
+ "m",
+ seconds / Second.per(Minute) as u64 % Minute.per(Hour) as u64
+ )?;
+ item!("s", seconds % Second.per(Minute) as u64)?;
+ item!("ms", nanoseconds / Nanosecond.per(Millisecond))?;
+ item!(
+ "µs",
+ nanoseconds / Nanosecond.per(Microsecond) as u32
+ % Microsecond.per(Millisecond) as u32
+ )?;
+ item!("ns", nanoseconds % Nanosecond.per(Microsecond) as u32)?;
}
Ok(())