From d4e3c2b62ca93c761ec49d40393775ec49bfc230 Mon Sep 17 00:00:00 2001 From: Vineeth Sai Date: Mon, 13 Jul 2026 14:08:57 -0700 Subject: [PATCH] Clamp rounded fractional seconds to the field width format_frac_seconds rounds the microseconds to the requested number of digits, but the rounding can carry up to a whole second (0.999 -> 1.0), producing a value with one digit too many. self.format then prints all of them, overflowing the fractional field (S rendered '10', SS rendered '100'). Clamp the rounded value to the maximum in-field value so it stays within the declared width. --- babel/dates.py | 5 ++++- tests/test_dates.py | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/babel/dates.py b/babel/dates.py index 69610a7f0..3727b8d19 100644 --- a/babel/dates.py +++ b/babel/dates.py @@ -1646,7 +1646,10 @@ def format_frac_seconds(self, num: int) -> str: of digits passed in. """ value = self.value.microsecond / 1000000 - return self.format(round(value, num) * 10**num, num) + # Rounding can carry the value up to a whole second (for example 0.999 + # rounds to 1.0), which would add a digit; clamp to the field width. + frac = min(int(round(value, num) * 10**num), 10**num - 1) + return self.format(frac, num) def format_milliseconds_in_day(self, num): msecs = ( diff --git a/tests/test_dates.py b/tests/test_dates.py index 12bb23433..b217deab9 100644 --- a/tests/test_dates.py +++ b/tests/test_dates.py @@ -177,6 +177,14 @@ def test_fractional_seconds_zero(self): t = time(15, 30, 0) assert dates.DateTimeFormat(t, locale='en_US')['SSSS'] == '0000' + def test_fractional_seconds_rounding_does_not_overflow_field(self): + t = time(1, 2, 3, 990000) + assert dates.DateTimeFormat(t, locale='en_US')['S'] == '9' + t = time(1, 2, 3, 999500) + assert dates.DateTimeFormat(t, locale='en_US')['SS'] == '99' + t = time(1, 2, 3, 999999) + assert dates.DateTimeFormat(t, locale='en_US')['SSSS'] == '9999' + def test_milliseconds_in_day(self): t = time(15, 30, 12, 345000) assert dates.DateTimeFormat(t, locale='en_US')['AAAA'] == '55812345'