diff --git a/babel/dates.py b/babel/dates.py index 7b626aa11..37c48235e 100644 --- a/babel/dates.py +++ b/babel/dates.py @@ -1638,7 +1638,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_date_time_format.py b/tests/test_date_time_format.py index 5ca620879..a60dc2242 100644 --- a/tests/test_date_time_format.py +++ b/tests/test_date_time_format.py @@ -175,6 +175,15 @@ def test_fractional_seconds(): assert DateTimeFormat(t, locale='en_US')['SSSSS'] == '00080' +def test_fractional_seconds_rounding_does_not_overflow_field(): + t = time(1, 2, 3, 990000) + assert DateTimeFormat(t, locale='en_US')['S'] == '9' + t = time(1, 2, 3, 999500) + assert DateTimeFormat(t, locale='en_US')['SS'] == '99' + t = time(1, 2, 3, 999999) + assert DateTimeFormat(t, locale='en_US')['SSSS'] == '9999' + + def test_fractional_seconds_zero(): t = time(15, 30, 0) assert DateTimeFormat(t, locale='en_US')['SSSS'] == '0000'