Skip to content

Commit 2a28ac3

Browse files
Implement rounding for Durations Debug output
Rounding is done like for printing floating point numbers. If the first digit which isn't printed (due to the precision parameter) is larger than '4', the number is rounded up.
1 parent 9eeb13f commit 2a28ac3

File tree

2 files changed

+51
-7
lines changed

2 files changed

+51
-7
lines changed

src/libcore/tests/time.rs

+16-6
Original file line numberDiff line numberDiff line change
@@ -202,13 +202,19 @@ fn debug_formatting_precision_zero() {
202202
assert_eq!(format!("{:.0?}", Duration::new(0, 123)), "123ns");
203203

204204
assert_eq!(format!("{:.0?}", Duration::new(0, 1_001)), "1µs");
205-
assert_eq!(format!("{:.0?}", Duration::new(0, 1_999)), "1µs");
205+
assert_eq!(format!("{:.0?}", Duration::new(0, 1_499)), "1µs");
206+
assert_eq!(format!("{:.0?}", Duration::new(0, 1_500)), "2µs");
207+
assert_eq!(format!("{:.0?}", Duration::new(0, 1_999)), "2µs");
206208

207209
assert_eq!(format!("{:.0?}", Duration::new(0, 1_000_001)), "1ms");
208-
assert_eq!(format!("{:.0?}", Duration::new(0, 1_999_999)), "1ms");
210+
assert_eq!(format!("{:.0?}", Duration::new(0, 1_499_999)), "1ms");
211+
assert_eq!(format!("{:.0?}", Duration::new(0, 1_500_000)), "2ms");
212+
assert_eq!(format!("{:.0?}", Duration::new(0, 1_999_999)), "2ms");
209213

210214
assert_eq!(format!("{:.0?}", Duration::new(1, 000_000_001)), "1s");
211-
assert_eq!(format!("{:.0?}", Duration::new(1, 999_999_999)), "1s");
215+
assert_eq!(format!("{:.0?}", Duration::new(1, 499_999_999)), "1s");
216+
assert_eq!(format!("{:.0?}", Duration::new(1, 500_000_000)), "2s");
217+
assert_eq!(format!("{:.0?}", Duration::new(1, 999_999_999)), "2s");
212218
}
213219

214220
#[test]
@@ -222,15 +228,19 @@ fn debug_formatting_precision_two() {
222228
assert_eq!(format!("{:.2?}", Duration::new(0, 1_000)), "1.00µs");
223229
assert_eq!(format!("{:.2?}", Duration::new(0, 7_001)), "7.00µs");
224230
assert_eq!(format!("{:.2?}", Duration::new(0, 7_100)), "7.10µs");
225-
assert_eq!(format!("{:.2?}", Duration::new(0, 1_999)), "1.99µs");
231+
assert_eq!(format!("{:.2?}", Duration::new(0, 7_109)), "7.11µs");
232+
assert_eq!(format!("{:.2?}", Duration::new(0, 7_199)), "7.20µs");
233+
assert_eq!(format!("{:.2?}", Duration::new(0, 1_999)), "2.00µs");
226234

227235
assert_eq!(format!("{:.2?}", Duration::new(0, 1_000_000)), "1.00ms");
228236
assert_eq!(format!("{:.2?}", Duration::new(0, 3_001_000)), "3.00ms");
229237
assert_eq!(format!("{:.2?}", Duration::new(0, 3_100_000)), "3.10ms");
230-
assert_eq!(format!("{:.2?}", Duration::new(0, 1_999_999)), "1.99ms");
238+
assert_eq!(format!("{:.2?}", Duration::new(0, 1_999_999)), "2.00ms");
231239

232240
assert_eq!(format!("{:.2?}", Duration::new(1, 000_000_000)), "1.00s");
233241
assert_eq!(format!("{:.2?}", Duration::new(4, 001_000_000)), "4.00s");
234242
assert_eq!(format!("{:.2?}", Duration::new(2, 100_000_000)), "2.10s");
235-
assert_eq!(format!("{:.2?}", Duration::new(8, 999_999_999)), "8.99s");
243+
assert_eq!(format!("{:.2?}", Duration::new(2, 104_990_000)), "2.10s");
244+
assert_eq!(format!("{:.2?}", Duration::new(2, 105_000_000)), "2.11s");
245+
assert_eq!(format!("{:.2?}", Duration::new(8, 999_999_999)), "9.00s");
236246
}

src/libcore/time.rs

+35-1
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ impl fmt::Debug for Duration {
498498
/// to be less than `10 * divisor`!
499499
fn fmt_decimal(
500500
f: &mut fmt::Formatter,
501-
integer_part: u64,
501+
mut integer_part: u64,
502502
mut fractional_part: u32,
503503
mut divisor: u32,
504504
) -> fmt::Result {
@@ -522,6 +522,40 @@ impl fmt::Debug for Duration {
522522
pos += 1;
523523
}
524524

525+
// If a precision < 9 was specified, there may be some non-zero
526+
// digits left that weren't written into the buffer. In that case we
527+
// need to perform rounding to match the semantics of printing
528+
// normal floating point numbers. However, we only need to do work
529+
// when rounding up. This happens if the first digit of the
530+
// remaining ones is >= 5.
531+
if fractional_part > 0 && fractional_part >= divisor * 5 {
532+
// Round up the number contained in the buffer. We go through
533+
// the buffer backwards and keep track of the carry.
534+
let mut rev_pos = pos;
535+
let mut carry = true;
536+
while carry && rev_pos > 0 {
537+
rev_pos -= 1;
538+
539+
// If the digit in the buffer is not '9', we just need to
540+
// increment it and can stop then (since we don't have a
541+
// carry anymore). Otherwise, we set it to '0' (overflow)
542+
// and continue.
543+
if buf[rev_pos] < b'9' {
544+
buf[rev_pos] += 1;
545+
carry = false;
546+
} else {
547+
buf[rev_pos] = b'0';
548+
}
549+
}
550+
551+
// If we still have the carry bit set, that means that we set
552+
// the whole buffer to '0's and need to increment the integer
553+
// part.
554+
if carry {
555+
integer_part += 1;
556+
}
557+
}
558+
525559
// If we haven't emitted a single fractional digit and the precision
526560
// wasn't set to a non-zero value, we don't print the decimal point.
527561
let end = f.precision().unwrap_or(pos);

0 commit comments

Comments
 (0)