@@ -1288,12 +1288,14 @@ macro_rules! try_from_secs {
12881288 let rem_msb = nanos_tmp & rem_msb_mask == 0 ;
12891289 let add_ns = !( rem_msb || ( is_even && is_tie) ) ;
12901290
1291- // note that neither `f32`, nor `f64` can represent
1292- // 0.999_999_999_5 exactly, so the nanos part
1293- // never will be equal to NANOS_PER_SEC
1291+ // f32 does not have enough presicion to trigger the second branch
1292+ // since it can not represent numbers between 0.999_999_940_395 and 1.0.
12941293 let nanos = nanos + add_ns as u32 ;
1295- debug_assert!( nanos < NANOS_PER_SEC ) ;
1296- ( 0 , nanos)
1294+ if ( $mant_bits == 23 ) || ( nanos != NANOS_PER_SEC ) {
1295+ ( 0 , nanos)
1296+ } else {
1297+ ( 1 , 0 )
1298+ }
12971299 } else if exp < $mant_bits {
12981300 let secs = u64 :: from( mant >> ( $mant_bits - exp) ) ;
12991301 let t = <$double_ty>:: from( ( mant << exp) & MANT_MASK ) ;
@@ -1309,11 +1311,16 @@ macro_rules! try_from_secs {
13091311 let rem_msb = nanos_tmp & rem_msb_mask == 0 ;
13101312 let add_ns = !( rem_msb || ( is_even && is_tie) ) ;
13111313
1312- // neither `f32`, nor `f64` can represent x.999_999_999_5 exactly,
1313- // so the nanos part never will be equal to NANOS_PER_SEC
1314+ // f32 does not have enough presicion to trigger the second branch.
1315+ // For example, it can not represent numbers between 1.999_999_880...
1316+ // and 2.0. Bigger values result in even smaller presicion of the
1317+ // fractional part.
13141318 let nanos = nanos + add_ns as u32 ;
1315- debug_assert!( nanos < NANOS_PER_SEC ) ;
1316- ( secs, nanos)
1319+ if ( $mant_bits == 23 ) || ( nanos != NANOS_PER_SEC ) {
1320+ ( secs, nanos)
1321+ } else {
1322+ ( secs + 1 , 0 )
1323+ }
13171324 } else if exp < 64 {
13181325 // the input has no fractional part
13191326 let secs = u64 :: from( mant) << ( exp - $mant_bits) ;
@@ -1433,6 +1440,14 @@ impl Duration {
14331440 /// // the conversion uses rounding with tie resolution to even
14341441 /// let res = Duration::try_from_secs_f64(0.999e-9);
14351442 /// assert_eq!(res, Ok(Duration::new(0, 1)));
1443+ /// let res = Duration::try_from_secs_f64(0.999_999_999_499);
1444+ /// assert_eq!(res, Ok(Duration::new(0, 999_999_999)));
1445+ /// let res = Duration::try_from_secs_f64(0.999_999_999_501);
1446+ /// assert_eq!(res, Ok(Duration::new(1, 0)));
1447+ /// let res = Duration::try_from_secs_f64(42.999_999_999_499);
1448+ /// assert_eq!(res, Ok(Duration::new(42, 999_999_999)));
1449+ /// let res = Duration::try_from_secs_f64(42.999_999_999_501);
1450+ /// assert_eq!(res, Ok(Duration::new(43, 0)));
14361451 ///
14371452 /// // this float represents exactly 976562.5e-9
14381453 /// let val = f64::from_bits(0x3F50_0000_0000_0000);
0 commit comments