From c8f3d8cccdbfdea8601a7031443f1412dd87f2bb Mon Sep 17 00:00:00 2001 From: KennyMcSimpson <70093673+KennyMcSimpson@users.noreply.github.com> Date: Sat, 24 Oct 2026 21:06:49 +0800 Subject: [PATCH] Fix week formatting at the maximum supported year Derive the next January weekday from December 31 to avoid constructing an out-of-range date for valid date.max and datetime.max values. Cover all six CLDR week rules at both supported date boundaries. --- babel/dates.py | 3 ++- tests/test_dates.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/babel/dates.py b/babel/dates.py index 7b626aa11..7e7830191 100644 --- a/babel/dates.py +++ b/babel/dates.py @@ -1705,7 +1705,8 @@ def get_week_of_year(self) -> int: date = datetime.date(self.value.year - 1, 12, 31) week = self.get_week_number(self.get_day_of_year(date), date.weekday()) elif week > 52: - weekday = datetime.date(self.value.year + 1, 1, 1).weekday() + # Derive the next January 1 without exceeding datetime's year range. + weekday = (datetime.date(self.value.year, 12, 31).weekday() + 1) % 7 if ( self.get_week_number(1, weekday) == 1 and 32 - (weekday - self.locale.first_week_day) % 7 <= self.value.day diff --git a/tests/test_dates.py b/tests/test_dates.py index 4f8c73907..1aa58c5ae 100644 --- a/tests/test_dates.py +++ b/tests/test_dates.py @@ -544,6 +544,38 @@ def test_datetime_format_get_week_number(): assert format.get_week_number(6) == 2 +@pytest.mark.parametrize(('value', 'formatter'), [ + (date.max, dates.format_date), + (datetime.max, dates.format_datetime), +]) +@pytest.mark.parametrize(('locale', 'expected'), [ + ('en_AU', '10000-W01-5'), # Monday, minimum one day. + ('aa_DJ', '9999-W53-7'), # Saturday, minimum one day. + ('en_US', '10000-W01-6'), # Sunday, minimum one day. + ('en_GB', '9999-W52-5'), # Monday, minimum four days. + ('dv_MV', '10000-W01-1'), # Friday, minimum one day. + ('pt_PT', '9999-W52-6'), # Sunday, minimum four days. +]) +def test_week_numbering_at_max_year(value, formatter, locale, expected): + assert formatter(value, "YYYY-'W'ww-e", locale=locale) == expected + + +@pytest.mark.parametrize(('value', 'formatter'), [ + (date.min, dates.format_date), + (datetime.min, dates.format_datetime), +]) +@pytest.mark.parametrize(('locale', 'expected'), [ + ('en_AU', '0001-W01-1'), + ('aa_DJ', '0001-W01-3'), + ('en_US', '0001-W01-2'), + ('en_GB', '0001-W01-1'), + ('dv_MV', '0001-W01-4'), + ('pt_PT', '0001-W01-2'), +]) +def test_week_numbering_at_min_year(value, formatter, locale, expected): + assert formatter(value, "YYYY-'W'ww-e", locale=locale) == expected + + def test_parse_pattern(): assert dates.parse_pattern("MMMMd").format == '%(MMMM)s%(d)s' assert (dates.parse_pattern("MMM d, yyyy").format ==