@@ -697,6 +697,44 @@ impl Duration {
697697 }
698698 }
699699
700+ /// The checked version of [`from_secs_f64`].
701+ ///
702+ /// [`from_secs_f64`]: Duration::from_secs_f64
703+ ///
704+ /// This constructor will return an `Err` if `secs` is not finite, negative or overflows `Duration`.
705+ ///
706+ /// # Examples
707+ /// ```
708+ /// #![feature(duration_checked_float)]
709+ ///
710+ /// use std::time::Duration;
711+ ///
712+ /// let dur = Duration::try_from_secs_f64(2.7);
713+ /// assert_eq!(dur, Ok(Duration::new(2, 700_000_000)));
714+ ///
715+ /// let negative = Duration::try_from_secs_f64(-5.0);
716+ /// assert!(negative.is_err());
717+ /// ```
718+ #[ unstable( feature = "duration_checked_float" , issue = "83400" ) ]
719+ #[ inline]
720+ pub const fn try_from_secs_f64 ( secs : f64 ) -> Result < Duration , FromSecsError > {
721+ const MAX_NANOS_F64 : f64 = ( ( u64:: MAX as u128 + 1 ) * ( NANOS_PER_SEC as u128 ) ) as f64 ;
722+ let nanos = secs * ( NANOS_PER_SEC as f64 ) ;
723+ if !nanos. is_finite ( ) {
724+ Err ( FromSecsError { kind : FromSecsErrorKind :: NonFinite } )
725+ } else if nanos >= MAX_NANOS_F64 {
726+ Err ( FromSecsError { kind : FromSecsErrorKind :: Overflow } )
727+ } else if nanos < 0.0 {
728+ Err ( FromSecsError { kind : FromSecsErrorKind :: Underflow } )
729+ } else {
730+ let nanos = nanos as u128 ;
731+ Ok ( Duration {
732+ secs : ( nanos / ( NANOS_PER_SEC as u128 ) ) as u64 ,
733+ nanos : ( nanos % ( NANOS_PER_SEC as u128 ) ) as u32 ,
734+ } )
735+ }
736+ }
737+
700738 /// Creates a new `Duration` from the specified number of seconds represented
701739 /// as `f32`.
702740 ///
@@ -732,6 +770,44 @@ impl Duration {
732770 }
733771 }
734772
773+ /// The checked version of [`from_secs_f32`].
774+ ///
775+ /// [`from_secs_f32`]: Duration::from_secs_f32
776+ ///
777+ /// This constructor will return an `Err` if `secs` is not finite, negative or overflows `Duration`.
778+ ///
779+ /// # Examples
780+ /// ```
781+ /// #![feature(duration_checked_float)]
782+ ///
783+ /// use std::time::Duration;
784+ ///
785+ /// let dur = Duration::try_from_secs_f32(2.7);
786+ /// assert_eq!(dur, Ok(Duration::new(2, 700_000_000)));
787+ ///
788+ /// let negative = Duration::try_from_secs_f32(-5.0);
789+ /// assert!(negative.is_err());
790+ /// ```
791+ #[ unstable( feature = "duration_checked_float" , issue = "83400" ) ]
792+ #[ inline]
793+ pub const fn try_from_secs_f32 ( secs : f32 ) -> Result < Duration , FromSecsError > {
794+ const MAX_NANOS_F32 : f32 = ( ( u64:: MAX as u128 + 1 ) * ( NANOS_PER_SEC as u128 ) ) as f32 ;
795+ let nanos = secs * ( NANOS_PER_SEC as f32 ) ;
796+ if !nanos. is_finite ( ) {
797+ Err ( FromSecsError { kind : FromSecsErrorKind :: NonFinite } )
798+ } else if nanos >= MAX_NANOS_F32 {
799+ Err ( FromSecsError { kind : FromSecsErrorKind :: Overflow } )
800+ } else if nanos < 0.0 {
801+ Err ( FromSecsError { kind : FromSecsErrorKind :: Underflow } )
802+ } else {
803+ let nanos = nanos as u128 ;
804+ Ok ( Duration {
805+ secs : ( nanos / ( NANOS_PER_SEC as u128 ) ) as u64 ,
806+ nanos : ( nanos % ( NANOS_PER_SEC as u128 ) ) as u32 ,
807+ } )
808+ }
809+ }
810+
735811 /// Multiplies `Duration` by `f64`.
736812 ///
737813 /// # Panics
@@ -1081,3 +1157,55 @@ impl fmt::Debug for Duration {
10811157 }
10821158 }
10831159}
1160+
1161+ /// An error which can be returned when converting a floating-point value of seconds
1162+ /// into a [`Duration`].
1163+ ///
1164+ /// This error is used as the error type for [`Duration::try_from_secs_f32`] and
1165+ /// [`Duration::try_from_secs_f64`].
1166+ ///
1167+ /// # Example
1168+ ///
1169+ /// ```
1170+ /// #![feature(duration_checked_float)]
1171+ ///
1172+ /// use std::time::Duration;
1173+ ///
1174+ /// if let Err(e) = Duration::try_from_secs_f32(-1.0) {
1175+ /// println!("Failed conversion to Duration: {}", e);
1176+ /// }
1177+ /// ```
1178+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
1179+ #[ unstable( feature = "duration_checked_float" , issue = "83400" ) ]
1180+ pub struct FromSecsError {
1181+ kind : FromSecsErrorKind ,
1182+ }
1183+
1184+ impl FromSecsError {
1185+ const fn description ( & self ) -> & ' static str {
1186+ match self . kind {
1187+ FromSecsErrorKind :: NonFinite => {
1188+ "got non-finite value when converting float to duration"
1189+ }
1190+ FromSecsErrorKind :: Overflow => "overflow when converting float to duration" ,
1191+ FromSecsErrorKind :: Underflow => "underflow when converting float to duration" ,
1192+ }
1193+ }
1194+ }
1195+
1196+ #[ unstable( feature = "duration_checked_float" , issue = "83400" ) ]
1197+ impl fmt:: Display for FromSecsError {
1198+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1199+ fmt:: Display :: fmt ( self . description ( ) , f)
1200+ }
1201+ }
1202+
1203+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
1204+ enum FromSecsErrorKind {
1205+ // Value is not a finite value (either infinity or NaN).
1206+ NonFinite ,
1207+ // Value is too large to store in a `Duration`.
1208+ Overflow ,
1209+ // Value is less than `0.0`.
1210+ Underflow ,
1211+ }
0 commit comments