@@ -1288,12 +1288,14 @@ macro_rules! try_from_secs {
1288
1288
let rem_msb = nanos_tmp & rem_msb_mask == 0 ;
1289
1289
let add_ns = !( rem_msb || ( is_even && is_tie) ) ;
1290
1290
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.
1294
1293
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
+ }
1297
1299
} else if exp < $mant_bits {
1298
1300
let secs = u64 :: from( mant >> ( $mant_bits - exp) ) ;
1299
1301
let t = <$double_ty>:: from( ( mant << exp) & MANT_MASK ) ;
@@ -1309,11 +1311,16 @@ macro_rules! try_from_secs {
1309
1311
let rem_msb = nanos_tmp & rem_msb_mask == 0 ;
1310
1312
let add_ns = !( rem_msb || ( is_even && is_tie) ) ;
1311
1313
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.
1314
1318
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
+ }
1317
1324
} else if exp < 64 {
1318
1325
// the input has no fractional part
1319
1326
let secs = u64 :: from( mant) << ( exp - $mant_bits) ;
@@ -1433,6 +1440,14 @@ impl Duration {
1433
1440
/// // the conversion uses rounding with tie resolution to even
1434
1441
/// let res = Duration::try_from_secs_f64(0.999e-9);
1435
1442
/// 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)));
1436
1451
///
1437
1452
/// // this float represents exactly 976562.5e-9
1438
1453
/// let val = f64::from_bits(0x3F50_0000_0000_0000);
0 commit comments