Skip to content

dates: fall back to the day period name when the flexible one is missing - #1406

Open
simpleqt wants to merge 2 commits into
python-babel:masterfrom
simpleqt:fix/period-without-flexible-names
Open

simpleqt wants to merge 2 commits into
python-babel:masterfrom
simpleqt:fix/period-without-flexible-names

Conversation

@simpleqt

Copy link
Copy Markdown

22 locales (az_Arab, en_Dsrt, en_Shaw and their country variants) have no names for the flexible day periods that a B or b pattern element asks for — their period data contains only am and pm — so formatting a valid pattern in a valid locale raised:

>>> from babel.dates import format_datetime
>>> format_datetime(datetime(2020, 1, 1, 11, 30), 'B', locale='az_Arab')
ValueError: Could not format period morning2 in az_Arab

DateTimeFormat.format_period() looked for the flexible period name (morning2) in up to four widths and gave up, even though the locale does name the day period that time belongs to. CLDR resolves a flexible day period with no name of its own to the day period containing the time, and a missing stand-alone name to the format name; the method now does the same, and still raises when neither has a name. Locales that do carry flexible names are unaffected: format_datetime(dt, 'B', locale='fi_FI') is still aamup. and the examples in the method's docstring are unchanged.

tests/test_dates.py::test_format_period_without_names_for_the_flexible_day_period fails on the default branch with ValueError: Could not format period morning2 and passes with the change; the whole test_dates.py is 2385 passed / 2 xfailed, and ruff check reports no findings.

Prepared with AI assistance; every line was verified by running the cases above.

format_interval() raises NotImplementedError for any skeleton whose CLDR
interval pattern defines the era ('G') or day period ('B') field, because
DateTimeFormat.extract() only understood y M d H h m a. The affected
skeletons (Gy, GyM, GyMd, GyMEd, GyMMM, GyMMMd, GyMMMEd, GyMMMM,
GyMMMMd, GyMMMMEd, GyMMMEEEEd, Bh, Bhm) are defined in interval_formats
for every locale, so format_interval(datetime(2020, 1, 1),
datetime(2021, 1, 1), 'Gy', locale='en') failed with
"Not implemented: extracting 'G' ...".

Extract those two fields, mirroring how they are rendered: the era index
from format_era() and the day period identifier from format_period().

Sweeping all locales, interval skeletons and instants (230,698 cases)
shows 20,220 NotImplementedError crashes on the base, 0 after the fix,
with no case that previously produced output changing its output.
22 locales (az_Arab, en_Dsrt, en_Shaw and their variants) carry no names
for the flexible day periods that a 'B' or 'b' pattern element asks for --
they only have 'am' and 'pm' -- so format_datetime() raised
ValueError: Could not format period morning2 in az_Arab for a valid
locale and a valid pattern.

CLDR resolves a flexible day period that has no name to the day period
containing the time, and a missing stand-alone name to the format name;
do the same here, and keep raising only when neither has a name.
Copilot AI balanced review requested due to automatic review settings October 24, 2026 15:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants