@@ -730,9 +730,9 @@ impl Duration {
730
730
/// // subnormal float
731
731
/// let res = Duration::from_secs_f64(f64::from_bits(1));
732
732
/// assert_eq!(res, Duration::new(0, 0));
733
- /// // conversion uses truncation, not rounding
733
+ /// // conversion uses rounding
734
734
/// let res = Duration::from_secs_f64(0.999e-9);
735
- /// assert_eq!(res, Duration::new(0, 0 ));
735
+ /// assert_eq!(res, Duration::new(0, 1 ));
736
736
/// ```
737
737
#[ stable( feature = "duration_float" , since = "1.38.0" ) ]
738
738
#[ must_use]
@@ -760,17 +760,17 @@ impl Duration {
760
760
/// let res = Duration::from_secs_f32(1e-20);
761
761
/// assert_eq!(res, Duration::new(0, 0));
762
762
/// let res = Duration::from_secs_f32(4.2e-7);
763
- /// assert_eq!(res, Duration::new(0, 419 ));
763
+ /// assert_eq!(res, Duration::new(0, 420 ));
764
764
/// let res = Duration::from_secs_f32(2.7);
765
- /// assert_eq!(res, Duration::new(2, 700_000_047 ));
765
+ /// assert_eq!(res, Duration::new(2, 700_000_048 ));
766
766
/// let res = Duration::from_secs_f32(3e10);
767
767
/// assert_eq!(res, Duration::new(30_000_001_024, 0));
768
768
/// // subnormal float
769
769
/// let res = Duration::from_secs_f32(f32::from_bits(1));
770
770
/// assert_eq!(res, Duration::new(0, 0));
771
- /// // conversion uses truncation, not rounding
771
+ /// // conversion uses rounding
772
772
/// let res = Duration::from_secs_f32(0.999e-9);
773
- /// assert_eq!(res, Duration::new(0, 0 ));
773
+ /// assert_eq!(res, Duration::new(0, 1 ));
774
774
/// ```
775
775
#[ stable( feature = "duration_float" , since = "1.38.0" ) ]
776
776
#[ must_use]
@@ -815,7 +815,7 @@ impl Duration {
815
815
/// use std::time::Duration;
816
816
///
817
817
/// let dur = Duration::new(2, 700_000_000);
818
- /// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_640 ));
818
+ /// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_641 ));
819
819
/// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847800, 0));
820
820
/// ```
821
821
#[ stable( feature = "duration_float" , since = "1.38.0" ) ]
@@ -838,8 +838,7 @@ impl Duration {
838
838
///
839
839
/// let dur = Duration::new(2, 700_000_000);
840
840
/// assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611));
841
- /// // note that truncation is used, not rounding
842
- /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_598));
841
+ /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_599));
843
842
/// ```
844
843
#[ stable( feature = "duration_float" , since = "1.38.0" ) ]
845
844
#[ must_use = "this returns the result of the operation, \
@@ -862,9 +861,8 @@ impl Duration {
862
861
/// let dur = Duration::new(2, 700_000_000);
863
862
/// // note that due to rounding errors result is slightly
864
863
/// // different from 0.859_872_611
865
- /// assert_eq!(dur.div_f32(3.14), Duration::new(0, 859_872_579));
866
- /// // note that truncation is used, not rounding
867
- /// assert_eq!(dur.div_f32(3.14e5), Duration::new(0, 8_598));
864
+ /// assert_eq!(dur.div_f32(3.14), Duration::new(0, 859_872_580));
865
+ /// assert_eq!(dur.div_f32(3.14e5), Duration::new(0, 8_599));
868
866
/// ```
869
867
#[ stable( feature = "duration_float" , since = "1.38.0" ) ]
870
868
#[ must_use = "this returns the result of the operation, \
@@ -1278,13 +1276,30 @@ macro_rules! try_from_secs {
1278
1276
} else if exp < 0 {
1279
1277
// the input is less than 1 second
1280
1278
let t = <$double_ty>:: from( mant) << ( $offset + exp) ;
1281
- let nanos = ( u128 :: from( NANOS_PER_SEC ) * u128 :: from( t) ) >> ( $mant_bits + $offset) ;
1282
- ( 0 , nanos as u32 )
1279
+ let nanos_offset = $mant_bits + $offset;
1280
+ let nanos_tmp = u128 :: from( NANOS_PER_SEC ) * u128 :: from( t) ;
1281
+ let nanos = ( nanos_tmp >> nanos_offset) as u32 ;
1282
+ if nanos_tmp & ( 1 << ( nanos_offset - 1 ) ) == 0 {
1283
+ ( 0 , nanos)
1284
+ } else if nanos + 1 != NANOS_PER_SEC {
1285
+ ( 0 , nanos + 1 )
1286
+ } else {
1287
+ ( 1 , 0 )
1288
+ }
1283
1289
} else if exp < $mant_bits {
1284
- let secs = mant >> ( $mant_bits - exp) ;
1290
+ let secs = u64 :: from ( mant >> ( $mant_bits - exp) ) ;
1285
1291
let t = <$double_ty>:: from( ( mant << exp) & MANT_MASK ) ;
1286
- let nanos = ( <$double_ty>:: from( NANOS_PER_SEC ) * t) >> $mant_bits;
1287
- ( u64 :: from( secs) , nanos as u32 )
1292
+ let nanos_tmp = <$double_ty>:: from( NANOS_PER_SEC ) * t;
1293
+ let nanos = ( nanos_tmp >> $mant_bits) as u32 ;
1294
+ if nanos_tmp & ( 1 << ( $mant_bits - 1 ) ) == 0 {
1295
+ ( secs, nanos)
1296
+ } else if nanos + 1 != NANOS_PER_SEC {
1297
+ ( secs, nanos + 1 )
1298
+ } else {
1299
+ // `secs + 1` can not overflow since `exp` is less than `$mant_bits`
1300
+ // and the latter is less than 64 bits for both `f32` and `f64`
1301
+ ( secs + 1 , 0 )
1302
+ }
1288
1303
} else if exp < 64 {
1289
1304
// the input has no fractional part
1290
1305
let secs = u64 :: from( mant) << ( exp - $mant_bits) ;
@@ -1315,17 +1330,17 @@ impl Duration {
1315
1330
/// let res = Duration::try_from_secs_f32(1e-20);
1316
1331
/// assert_eq!(res, Ok(Duration::new(0, 0)));
1317
1332
/// let res = Duration::try_from_secs_f32(4.2e-7);
1318
- /// assert_eq!(res, Ok(Duration::new(0, 419 )));
1333
+ /// assert_eq!(res, Ok(Duration::new(0, 420 )));
1319
1334
/// let res = Duration::try_from_secs_f32(2.7);
1320
- /// assert_eq!(res, Ok(Duration::new(2, 700_000_047 )));
1335
+ /// assert_eq!(res, Ok(Duration::new(2, 700_000_048 )));
1321
1336
/// let res = Duration::try_from_secs_f32(3e10);
1322
1337
/// assert_eq!(res, Ok(Duration::new(30_000_001_024, 0)));
1323
1338
/// // subnormal float:
1324
1339
/// let res = Duration::try_from_secs_f32(f32::from_bits(1));
1325
1340
/// assert_eq!(res, Ok(Duration::new(0, 0)));
1326
- /// // conversion uses truncation, not rounding
1341
+ /// // conversion uses rounding
1327
1342
/// let res = Duration::try_from_secs_f32(0.999e-9);
1328
- /// assert_eq!(res, Ok(Duration::new(0, 0 )));
1343
+ /// assert_eq!(res, Ok(Duration::new(0, 1 )));
1329
1344
///
1330
1345
/// let res = Duration::try_from_secs_f32(-5.0);
1331
1346
/// assert!(res.is_err());
@@ -1372,9 +1387,9 @@ impl Duration {
1372
1387
/// // subnormal float
1373
1388
/// let res = Duration::try_from_secs_f64(f64::from_bits(1));
1374
1389
/// assert_eq!(res, Ok(Duration::new(0, 0)));
1375
- /// // conversion uses truncation, not rounding
1390
+ /// // conversion uses rounding
1376
1391
/// let res = Duration::try_from_secs_f32(0.999e-9);
1377
- /// assert_eq!(res, Ok(Duration::new(0, 0 )));
1392
+ /// assert_eq!(res, Ok(Duration::new(0, 1 )));
1378
1393
///
1379
1394
/// let res = Duration::try_from_secs_f64(-5.0);
1380
1395
/// assert!(res.is_err());
0 commit comments