Skip to content

dates: return a location without a region when the locale has no name for it - #1405

Open
simpleqt wants to merge 1 commit into
python-babel:masterfrom
simpleqt:fix/timezone-location-missing-region-name
Open

simpleqt wants to merge 1 commit into
python-babel:masterfrom
simpleqt:fix/timezone-location-missing-region-name

Conversation

@simpleqt

@simpleqt simpleqt commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

get_timezone_location() falls back to the CLDR region ZZ ("unknown region") when the zone's territory has no name in the requested locale, but it then looked that name up with [] rather than .get(). Any locale that does not translate ZZ therefore raised KeyError: 'ZZ' for a perfectly valid zone — 183 of the 1,121 locale identifiers: python >>> from babel.dates import get_timezone, get_timezone_location, get_timezone_name >>> tz = get_timezone('Europe/Paris') >>> get_timezone_location(tz, locale='aa') KeyError: 'ZZ' >>> get_timezone_name(tz, locale='aa') # reaches the same code with no zone variant KeyError: 'ZZ' get_timezone_name() calls get_timezone_location() when no zone_variant is given, so the crash also surfaced through the name lookup, which is the more common entry point. The change keeps the region name optional: when the locale cannot name the region at all, the location is returned without one, which is what the location format degenerates to. Locales that do name it are untouched (en still gives Canada (St. John's) Time, de_DE still gives Kanada (St. John's) (Ortszeit)), and return_city=True is unaffected. tests/test_dates.py::test_get_timezone_location_without_a_region_name covers the fallback and the unchanged case: 2 failed with KeyError: 'ZZ' before, 33 passed in the surrounding timezone tests after, and the full test_dates.py plus test_date_intervals.py are 2400 passed / 2 xfailed. ruff check reports no findings on either file. Prepared with AI assistance; every line was verified by running the cases above.

Copilot AI balanced review requested due to automatic review settings October 24, 2026 15:17

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.

@akx akx left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What are the format_interval changes in this PR?

… for it

get_timezone_location() falls back to the CLDR region 'ZZ' ('unknown
region') when the zone's territory has no name in the locale, but it then
looked that name up with [] instead of .get(), so every locale that does
not translate 'ZZ' -- 347 of the 1,121 locales -- raised KeyError: 'ZZ'
for a perfectly valid zone.  get_timezone_name() reaches the same code
when no zone variant is given, so the crash surfaced through the public
name lookup too.

Leave the region out of the result in that case, which is what the
location format degenerates to when the locale cannot name the region.
@simpleqt
simpleqt force-pushed the fix/timezone-location-missing-region-name branch from 8a5ffe9 to 12c84da Compare November 2, 2026 16:28
@simpleqt

simpleqt commented Nov 2, 2026

Copy link
Copy Markdown
Contributor Author

They are out of scope and I have removed them. They came from an earlier commit on this branch that taught DateTimeFormat.extract() the G (era) and B (day period) fields so that format_interval() stops raising NotImplementedError for skeletons like Gy / Bh - a real gap, but unrelated to returning a location without a region, and it is now gone: the diff is babel/dates.py plus the two new timezone tests and nothing else. Happy to open the era/day-period fix as its own pull request if you want it.

Two corrections while I am here:

  • The description said the bug affects "173 of the 1,121 locales"; measured against this checkout it is 183 locale identifiers that raise KeyError: 'ZZ' (68 of them plain language tags, the rest being locales that genuinely have no ZZ territory name). I have corrected the number in the description.
  • Removing the earlier commit does not affect the fix: without it the timezone case still returns St. John's for aa and Canada (St. John's) Time for en, and with it the KeyError remains. A sweep over all 1,121 locale identifiers now fails for 0 of them, against 183 before.

tests/test_dates.py and tests/test_date_intervals.py: 2,394 passed on the base, 2,396 with the final change (the base plus the two new timezone tests), and ruff is clean on the changed files.

@codspeed

codspeed Bot commented Nov 2, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 88 untouched benchmarks


Comparing simpleqt:fix/timezone-location-missing-region-name (12c84da) with master (7576e5d)

Open in CodSpeed

@codecov

codecov Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.59%. Comparing base (e2a1791) to head (12c84da).
⚠️ Report is 20 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1405      +/-   ##
==========================================
+ Coverage   93.37%   93.59%   +0.22%     
==========================================
  Files          27       27              
  Lines        4922     4953      +31     
==========================================
+ Hits         4596     4636      +40     
+ Misses        326      317       -9     
Flag Coverage Δ
macos-14-3.10 92.63% <100.00%> (+0.16%) ⬆️
macos-14-3.11 92.57% <100.00%> (+0.16%) ⬆️
macos-14-3.12 92.83% <100.00%> (+0.22%) ⬆️
macos-14-3.13 92.83% <100.00%> (+0.22%) ⬆️
macos-14-3.14 92.81% <100.00%> (+0.22%) ⬆️
macos-14-3.15 92.81% <100.00%> (+0.22%) ⬆️
macos-14-3.8 92.50% <100.00%> (+0.16%) ⬆️
macos-14-3.9 92.56% <100.00%> (+0.16%) ⬆️
macos-14-pypy3.10 92.63% <100.00%> (+0.16%) ⬆️
ubuntu-24.04-3.10 92.65% <100.00%> (+0.16%) ⬆️
ubuntu-24.04-3.11 92.59% <100.00%> (+0.16%) ⬆️
ubuntu-24.04-3.12 92.85% <100.00%> (+0.22%) ⬆️
ubuntu-24.04-3.13 92.85% <100.00%> (+0.22%) ⬆️
ubuntu-24.04-3.14 92.83% <100.00%> (+0.22%) ⬆️
ubuntu-24.04-3.15 92.83% <100.00%> (+0.22%) ⬆️
ubuntu-24.04-3.8 92.52% <100.00%> (+0.16%) ⬆️
ubuntu-24.04-3.9 92.58% <100.00%> (+0.16%) ⬆️
ubuntu-24.04-pypy3.10 92.65% <100.00%> (+0.16%) ⬆️
windows-2022-3.10 92.64% <100.00%> (+0.16%) ⬆️
windows-2022-3.11 92.58% <100.00%> (+0.16%) ⬆️
windows-2022-3.12 92.84% <100.00%> (+0.22%) ⬆️
windows-2022-3.13 92.84% <100.00%> (+0.22%) ⬆️
windows-2022-3.14 92.82% <100.00%> (+0.22%) ⬆️
windows-2022-3.15 92.82% <100.00%> (+0.22%) ⬆️
windows-2022-3.8 92.61% <100.00%> (+0.16%) ⬆️
windows-2022-3.9 92.57% <100.00%> (+0.16%) ⬆️
windows-2022-pypy3.10 92.64% <100.00%> (+0.16%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants