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);