fmt: fix buffer sizes when printing durations

The ISO 8601 buffer for durations was sized for `SignedDuration::MIN`,
but the longest output is a negative duration with 16 digits of hours
and two digit minutes and seconds, e.g.,
`-PT2562047788015214H59M59.999999999S`, which is 36 bytes.

Similarly, the friendly format buffer for `std::time::Duration` didn't
account for the `+` prefix written by `Direction::ForceSign`.

Fixes #654
This commit is contained in:
dualfroz committed 2026-10-13 09:55:38 -04:00
1 parent e14c262673
commit a580c0b437
3 files changed
+37 -5

No files matched your search

+10
View File
@@ -1,5 +1,15 @@
# CHANGELOG
0.2.39 (TBD)
============
TODO
Bug fixes:
* [#654](https://github.com/BurntSushi/jiff/issues/654):
Fixes a panic when printing some very large durations.
0.2.38 (2026-10-06)
===================
This release updates Jiff's bundled copy of the [IANA Time Zone Database]
+9 -2
View File
@@ -50,8 +50,9 @@ const MAX_SIGNED_DURATION_LEN: usize = 194;
///
/// Note that this is shorter than `MAX_SIGNED_DURATION` because one cannot
/// get a negative formatted duration from a `std::time::Duration`. So there's
/// no way to get an ` ago` suffix (or a `-` prefix).
const MAX_UNSIGNED_DURATION_LEN: usize = 190;
/// no way to get an ` ago` suffix (or a `-` prefix). It can still get a `+`
/// prefix with `Direction::ForceSign` though, which is counted here.
const MAX_UNSIGNED_DURATION_LEN: usize = 191;
/// Configuration for [`SpanPrinter::designator`].
///
@@ -4169,5 +4170,11 @@ mod tests {
p.unsigned_duration_to_string(&udur),
@"00005124095576030430 hours, 00000000000000000059 minutes, 00000000000000000059 seconds, 00000000000000000999 milliseconds, 00000000000000000999 microseconds, 00000000000000000999 nanoseconds",
);
let p = p.direction(Direction::ForceSign);
insta::assert_snapshot!(
p.unsigned_duration_to_string(&udur),
@"+00005124095576030430 hours, 00000000000000000059 minutes, 00000000000000000059 seconds, 00000000000000000999 milliseconds, 00000000000000000999 microseconds, 00000000000000000999 nanoseconds",
);
}
}
+18 -3
View File
@@ -134,9 +134,11 @@ const MAX_SPAN_LEN: usize = 78;
/// Defines the maximum possible length (in bytes) of a duration printed in the
/// Temporal ISO 8601 format.
///
/// This applies to both signed and unsigned durations. Unsigned durations have
/// one more digit, but signed durations can have a negative sign.
const MAX_DURATION_LEN: usize = 35;
/// This applies to both signed and unsigned durations. The longest one isn't
/// at either extreme. It's a negative duration with 16 digits of hours and
/// two digit minutes and seconds, e.g.,
/// `-PT2562047788015214H59M59.999999999S`.
const MAX_DURATION_LEN: usize = 36;
#[derive(Clone, Debug)]
pub(super) struct DateTimePrinter {
@@ -1897,6 +1899,15 @@ mod tests {
p(i64::MAX, 999_999_999),
@"PT2562047788015215H30M7.999999999S",
);
insta::assert_snapshot!(
p(-(2_562_047_788_015_214 * 3_600 + 3_599), -999_999_999),
@"-PT2562047788015214H59M59.999999999S",
);
insta::assert_snapshot!(
p(2_562_047_788_015_214 * 3_600 + 3_599, 999_999_999),
@"PT2562047788015214H59M59.999999999S",
);
}
#[cfg(not(miri))]
@@ -1929,5 +1940,9 @@ mod tests {
p(u64::MAX, 999_999_999),
@"PT5124095576030431H15.999999999S",
);
insta::assert_snapshot!(
p(5_124_095_576_030_430 * 3_600 + 3_599, 999_999_999),
@"PT5124095576030430H59M59.999999999S",
);
}
}