@@ -2495,6 +2495,33 @@ impl core::fmt::Debug for SignedDuration {
24952495 }
24962496}
24972497
2498+ /// Fallibly converts a [`std::time::Duration`] to a `SignedDuration`.
2499+ ///
2500+ /// # Errors
2501+ ///
2502+ /// This fails when the duration's second component exceeds `i64::MAX`.
2503+ ///
2504+ /// # Examples
2505+ ///
2506+ /// ```
2507+ /// use std::time::Duration;
2508+ ///
2509+ /// use jiff::SignedDuration;
2510+ ///
2511+ /// let dur = Duration::new(5, 123_000_000);
2512+ /// let sdur = SignedDuration::try_from(dur)?;
2513+ /// assert_eq!(sdur, SignedDuration::new(5, 123_000_000));
2514+ ///
2515+ /// let dur = Duration::new(i64::MAX as u64, 999_999_999);
2516+ /// let sdur = SignedDuration::try_from(dur)?;
2517+ /// assert_eq!(sdur, SignedDuration::new(i64::MAX, 999_999_999));
2518+ ///
2519+ /// // Some failure cases:
2520+ /// assert!(SignedDuration::try_from(Duration::new(i64::MAX as u64 + 1, 0)).is_err());
2521+ /// assert!(SignedDuration::try_from(Duration::new(u64::MAX, 0)).is_err());
2522+ ///
2523+ /// # Ok::<(), Box<dyn std::error::Error>>(())
2524+ /// ```
24982525impl TryFrom < Duration > for SignedDuration {
24992526 type Error = Error ;
25002527
@@ -2507,16 +2534,40 @@ impl TryFrom<Duration> for SignedDuration {
25072534 }
25082535}
25092536
2537+ /// Fallibly converts a `SignedDuration` to a [`std::time::Duration`].
2538+ ///
2539+ /// # Errors
2540+ ///
2541+ /// This fails when the signed duration is negative.
2542+ ///
2543+ /// # Examples
2544+ ///
2545+ /// ```
2546+ /// use std::time::Duration;
2547+ ///
2548+ /// use jiff::SignedDuration;
2549+ ///
2550+ /// let sdur = SignedDuration::new(5, 123_000_000);
2551+ /// let dur = Duration::try_from(sdur)?;
2552+ /// assert_eq!(dur, Duration::new(5, 123_000_000));
2553+ ///
2554+ /// // Some failure cases:
2555+ /// assert!(Duration::try_from(SignedDuration::new(-5, 0)).is_err());
2556+ /// assert!(Duration::try_from(SignedDuration::new(-5, -1)).is_err());
2557+ /// assert!(Duration::try_from(SignedDuration::new(0, -1)).is_err());
2558+ ///
2559+ /// # Ok::<(), Box<dyn std::error::Error>>(())
2560+ /// ```
25102561impl TryFrom < SignedDuration > for Duration {
25112562 type Error = Error ;
25122563
25132564 fn try_from ( sd : SignedDuration ) -> Result < Duration , Error > {
25142565 let secs = u64:: try_from ( sd. as_secs ( ) )
2515- . map_err ( |_| SpecialBoundsError :: UnsignedDurationSeconds ) ?;
2516- // Guaranteed to succeed because the above only succeeds
2517- // when `sd` is non-negative. And when `sd` is non-negative,
2518- // we are guaranteed that 0<=nanos<=999,999,999.
2519- let nanos = u32 :: try_from ( sd . subsec_nanos ( ) ) . unwrap ( ) ;
2566+ . map_err ( |_| SpecialBoundsError :: SignedToUnsignedDuration ) ?;
2567+ // This could still be negative in the case where
2568+ // `sd.as_secs()` is zero.
2569+ let nanos = u32 :: try_from ( sd . subsec_nanos ( ) )
2570+ . map_err ( |_| SpecialBoundsError :: SignedToUnsignedDuration ) ? ;
25202571 Ok ( Duration :: new ( secs, nanos) )
25212572 }
25222573}
0 commit comments