Skip to content

Commit

Permalink
Add Duration::checked_neg
Browse files Browse the repository at this point in the history
  • Loading branch information
jhpratt committed Mar 20, 2024
1 parent c01a9b5 commit e96bc85
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
9 changes: 9 additions & 0 deletions tests/duration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,15 @@ fn checked_div_regression() {
Some(Duration::new(0, 142_857_143)) // manually verified
);
}

#[rstest]
#[case(5.seconds(), Some((-5).seconds()))]
#[case((-5).seconds(), Some(5.seconds()))]
#[case(Duration::MIN, None)]
fn checked_neg(#[case] duration: Duration, #[case] expected: Option<Duration>) {
assert_eq!(duration.checked_neg(), expected);
}

#[rstest]
#[case(5.seconds(), 5.seconds(), 10.seconds())]
#[case(Duration::MAX, 1.nanoseconds(), Duration::MAX)]
Expand Down
21 changes: 20 additions & 1 deletion time/src/duration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1023,6 +1023,25 @@ impl Duration {
// Safety: `nanoseconds` is in range.
unsafe { Some(Self::new_unchecked(secs, nanos)) }
}

/// Computes `-self`, returning `None` if the result would overflow.
///
/// ```rust
/// # use time::ext::NumericalDuration;
/// # use time::Duration;
/// assert_eq!(5.seconds().checked_neg(), Some((-5).seconds()));
/// assert_eq!(Duration::MIN.checked_neg(), None);
/// ```
pub const fn checked_neg(self) -> Option<Self> {
if self.seconds == i64::MIN {
None
} else {
Some(Self::new_ranged_unchecked(
-self.seconds,
self.nanoseconds.neg(),
))
}
}
// endregion checked arithmetic

// region: saturating arithmetic
Expand Down Expand Up @@ -1338,7 +1357,7 @@ impl Neg for Duration {
type Output = Self;

fn neg(self) -> Self::Output {
Self::new_ranged_unchecked(-self.seconds, self.nanoseconds.neg())
self.checked_neg().expect("overflow when negating duration")
}
}

Expand Down

0 comments on commit e96bc85

Please sign in to comment.