Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion library/core/src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1318,7 +1318,33 @@ impl fmt::Debug for Duration {
// 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.
let integer_part = if fractional_part > 0 && fractional_part >= divisor * 5 {
let integer_part = if fractional_part > 0 && fractional_part == divisor * 5 {
let last_digit_is_odd = if pos > 0 {
(buf[pos - 1] - b'0') % 2 == 1
} else {
// No fractional digits - check the integer part
(integer_part % 2) == 1
};

if last_digit_is_odd {
let mut rev_pos = pos;
let mut carry = true;
while carry && rev_pos > 0 {
rev_pos -= 1;

if buf[rev_pos] < b'9' {
buf[rev_pos] += 1;
carry = false;
} else {
buf[rev_pos] = b'0';
}
}

if carry { integer_part.checked_add(1) } else { Some(integer_part) }
} else {
Some(integer_part)
}
} else 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;
Expand Down
10 changes: 9 additions & 1 deletion library/coretests/tests/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,6 @@ fn debug_formatting_precision_two() {
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(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");
}

Expand Down Expand Up @@ -480,6 +479,15 @@ fn debug_formatting_precision_high() {
assert_eq!(format!("{:.20?}", Duration::new(4, 001_000_000)), "4.00100000000000000000s");
}

#[test]
fn debug_formatting_round_to_even() {
assert_eq!(format!("{:.0?}", Duration::new(1, 500_000_000)), "2s");
assert_eq!(format!("{:.0?}", Duration::new(2, 500_000_000)), "2s");
assert_eq!(format!("{:.0?}", Duration::new(0, 1_500_000)), "2ms");
assert_eq!(format!("{:.0?}", Duration::new(0, 2_500_000)), "2ms");
assert_eq!(format!("{:.2?}", Duration::new(2, 105_000_000)), "2.10s");
}

#[test]
fn duration_const() {
// test that the methods of `Duration` are usable in a const context
Expand Down
Loading