diff --git a/src/libcore/tests/time.rs b/src/libcore/tests/time.rs index bfb5369cf8f..b0abdc749f6 100644 --- a/src/libcore/tests/time.rs +++ b/src/libcore/tests/time.rs @@ -202,13 +202,19 @@ fn debug_formatting_precision_zero() { assert_eq!(format!("{:.0?}", Duration::new(0, 123)), "123ns"); assert_eq!(format!("{:.0?}", Duration::new(0, 1_001)), "1µs"); - assert_eq!(format!("{:.0?}", Duration::new(0, 1_999)), "1µs"); + assert_eq!(format!("{:.0?}", Duration::new(0, 1_499)), "1µs"); + assert_eq!(format!("{:.0?}", Duration::new(0, 1_500)), "2µs"); + assert_eq!(format!("{:.0?}", Duration::new(0, 1_999)), "2µs"); assert_eq!(format!("{:.0?}", Duration::new(0, 1_000_001)), "1ms"); - assert_eq!(format!("{:.0?}", Duration::new(0, 1_999_999)), "1ms"); + assert_eq!(format!("{:.0?}", Duration::new(0, 1_499_999)), "1ms"); + assert_eq!(format!("{:.0?}", Duration::new(0, 1_500_000)), "2ms"); + assert_eq!(format!("{:.0?}", Duration::new(0, 1_999_999)), "2ms"); assert_eq!(format!("{:.0?}", Duration::new(1, 000_000_001)), "1s"); - assert_eq!(format!("{:.0?}", Duration::new(1, 999_999_999)), "1s"); + assert_eq!(format!("{:.0?}", Duration::new(1, 499_999_999)), "1s"); + assert_eq!(format!("{:.0?}", Duration::new(1, 500_000_000)), "2s"); + assert_eq!(format!("{:.0?}", Duration::new(1, 999_999_999)), "2s"); } #[test] @@ -222,15 +228,19 @@ fn debug_formatting_precision_two() { assert_eq!(format!("{:.2?}", Duration::new(0, 1_000)), "1.00µs"); assert_eq!(format!("{:.2?}", Duration::new(0, 7_001)), "7.00µs"); assert_eq!(format!("{:.2?}", Duration::new(0, 7_100)), "7.10µs"); - assert_eq!(format!("{:.2?}", Duration::new(0, 1_999)), "1.99µs"); + assert_eq!(format!("{:.2?}", Duration::new(0, 7_109)), "7.11µs"); + assert_eq!(format!("{:.2?}", Duration::new(0, 7_199)), "7.20µs"); + assert_eq!(format!("{:.2?}", Duration::new(0, 1_999)), "2.00µs"); assert_eq!(format!("{:.2?}", Duration::new(0, 1_000_000)), "1.00ms"); assert_eq!(format!("{:.2?}", Duration::new(0, 3_001_000)), "3.00ms"); assert_eq!(format!("{:.2?}", Duration::new(0, 3_100_000)), "3.10ms"); - assert_eq!(format!("{:.2?}", Duration::new(0, 1_999_999)), "1.99ms"); + assert_eq!(format!("{:.2?}", Duration::new(0, 1_999_999)), "2.00ms"); assert_eq!(format!("{:.2?}", Duration::new(1, 000_000_000)), "1.00s"); assert_eq!(format!("{:.2?}", Duration::new(4, 001_000_000)), "4.00s"); assert_eq!(format!("{:.2?}", Duration::new(2, 100_000_000)), "2.10s"); - assert_eq!(format!("{:.2?}", Duration::new(8, 999_999_999)), "8.99s"); + assert_eq!(format!("{:.2?}", Duration::new(2, 104_990_000)), "2.10s"); + assert_eq!(format!("{:.2?}", Duration::new(2, 105_000_000)), "2.11s"); + assert_eq!(format!("{:.2?}", Duration::new(8, 999_999_999)), "9.00s"); } diff --git a/src/libcore/time.rs b/src/libcore/time.rs index a0a48e8493c..34bf3637f29 100644 --- a/src/libcore/time.rs +++ b/src/libcore/time.rs @@ -498,7 +498,7 @@ impl fmt::Debug for Duration { /// to be less than `10 * divisor`! fn fmt_decimal( f: &mut fmt::Formatter, - integer_part: u64, + mut integer_part: u64, mut fractional_part: u32, mut divisor: u32, ) -> fmt::Result { @@ -522,6 +522,40 @@ impl fmt::Debug for Duration { pos += 1; } + // If a precision < 9 was specified, there may be some non-zero + // digits left that weren't written into the buffer. In that case we + // need to perform rounding to match the semantics of printing + // normal floating point numbers. However, we only need to do work + // when rounding up. This happens if the first digit of the + // remaining ones is >= 5. + if fractional_part > 0 && fractional_part >= divisor * 5 { + // Round up the number contained in the buffer. We go through + // the buffer backwards and keep track of the carry. + let mut rev_pos = pos; + let mut carry = true; + while carry && rev_pos > 0 { + rev_pos -= 1; + + // If the digit in the buffer is not '9', we just need to + // increment it and can stop then (since we don't have a + // carry anymore). Otherwise, we set it to '0' (overflow) + // and continue. + if buf[rev_pos] < b'9' { + buf[rev_pos] += 1; + carry = false; + } else { + buf[rev_pos] = b'0'; + } + } + + // If we still have the carry bit set, that means that we set + // the whole buffer to '0's and need to increment the integer + // part. + if carry { + integer_part += 1; + } + } + // If we haven't emitted a single fractional digit and the precision // wasn't set to a non-zero value, we don't print the decimal point. let end = f.precision().unwrap_or(pos);