fix(api): correct DST spring-forward handling in parse_time_range#39231
Open
lntutor wants to merge 1 commit into
Open
fix(api): correct DST spring-forward handling in parse_time_range#39231lntutor wants to merge 1 commit into
lntutor wants to merge 1 commit into
Conversation
The NonExistentTimeError branch adjusted a non-existent (spring-forward) wall-clock time by a hardcoded +1 hour, which assumes every DST gap is exactly one hour. Real tzdata has gaps of other sizes: - Gaps longer than one hour (e.g. Antarctica/Troll, +2h): adding one hour lands inside the gap, so the retry tz.localize(..., is_dst=None) raises NonExistentTimeError again -- uncaught, leaking a raw pytz exception out of a function documented to raise only ValueError. - Gaps shorter than one hour (e.g. Australia/Lord_Howe, +30min): the result is shifted an hour instead of 30 minutes, so the returned UTC instant is wrong and silently drops data from analytics time ranges. Resolve the non-existent time with tz.normalize(tz.localize(dt, is_dst=False)) instead, which shifts forward by exactly the gap size for any offset change and matches zoneinfo fold=0. Standard one-hour gaps are unchanged (America/New_York 02:30 -> 07:30 UTC). Replaces the mock-based nonexistent-time test (which asserted the old call sequence) with real-timezone tests covering the standard, >1h, and <1h gaps. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N6RtoHuxrDqTUo9Mw9h4Cv
Contributor
Pyrefly Type Coverage
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #39230
Summary
libs/datetime_utils.py::parse_time_rangeresolved a non-existent (DST spring-forward) wall-clock time by adding a hardcoded one hour, assuming every gap is exactly one hour. Real tzdata has other gap sizes, producing two bugs:+1hlands inside the gap, so the retrytz.localize(..., is_dst=None)raisesNonExistentTimeErroragain — uncaught, leaking a raw pytz exception out of a function documented to raise onlyValueError.Change
tz.normalize(tz.localize(dt, is_dst=False))shifts a non-existent time forward by exactly the gap size for any offset change (30 min, 1 h, 2 h, ...), matchingzoneinfofold=0. It never re-raises. Standard one-hour gaps are unchanged (America/New_York 02:30 → 07:30 UTC). TheAmbiguousTimeError(fall-back) branch is untouched.Verified the fix matches stdlib
zoneinfofold=0 for Antarctica/Troll, Australia/Lord_Howe, Pacific/Apia, and America/New_York.Tests
Replaces the previous mock-based
test_parse_time_range_dst_nonexistent_time(which patchedpytz.timezoneand asserted the oldlocalizecall sequence rather than a real result — it used Jan 1, not an actual DST transition) with real-timezone tests:America/New_York02:30 → 07:30 UTC (unchanged behavior),Antarctica/Troll01:30 must not raise and resolves to 01:30 UTC,Australia/Lord_Howe02:15 → 2024-10-05 15:45 UTC.All 25
test_datetime_utilstests pass; the fulltests/unit_tests/libssuite stays green;ruff checkandruff format --checkclean.