Skip to content

Fix US timezone fold handling - #441

Open
deepakganesh78 wants to merge 1 commit into
mahmoud:masterfrom
deepakganesh78:fix/issue141-us-timezone-fold
Open

Fix US timezone fold handling#441
deepakganesh78 wants to merge 1 commit into
mahmoud:masterfrom
deepakganesh78:fix/issue141-us-timezone-fold

Conversation

@deepakganesh78

@deepakganesh78 deepakganesh78 commented Aug 2, 2026

Copy link
Copy Markdown

Addresses the USTimeZone half of #141.

Reproduction

On current master, ambiguous US/Eastern wall times at the 2011 fall DST transition ignore datetime.fold:

from datetime import datetime
from boltons.timeutils import Eastern

unfolded = datetime(2011, 11, 6, 1, 30, tzinfo=Eastern, fold=0)
folded = datetime(2011, 11, 6, 1, 30, tzinfo=Eastern, fold=1)
print(unfolded.utcoffset(), unfolded.tzname())  # -05:00 EST, should be -04:00 EDT
print(folded.utcoffset(), folded.tzname())      # -05:00 EST

Converting from UTC has the same problem: both 2011-11-06T05:30Z and 2011-11-06T06:30Z map to a local 01:30 with fold=0, so the two distinct instants become indistinguishable.

Root cause

USTimeZone.dst() used a single [start, end) DST interval and stored the DST end transition as 1am standard time, so the repeated fall-back hour was always treated as standard time. USTimeZone also relied on the base tzinfo.fromutc(), which cannot mark repeated local times with fold=1.

Fix

  • Correct the US DST transition end constants to 2am standard time (matching the transition rule the comments already describe).
  • Factor transition-range selection into USTimeZone._dst_range().
  • Make dst() fold-aware for both the repeated hour (fall back) and the missing hour (spring forward), following PEP 495 semantics.
  • Implement USTimeZone.fromutc() so that the second occurrence of a repeated local time is returned with fold=1.

Dependency-free, no new imports, and compatible with the Python versions boltons supports (fold is read via getattr(dt, 'fold', 0)).

Scope note

This PR deliberately covers only USTimeZone. The issue also mentions LocalTZInfo, whose is_dst() delegates to time.mktime()/time.localtime(); making that fold-aware requires gap/ambiguity detection against the host's own zone rules and cannot be regression-tested portably (time.tzset is unavailable on Windows, and the class caches time.timezone/time.altzone at import). I did not want to ship an untested change to it in the same PR — happy to follow up separately if you'd like that half too, or to adjust the scope of this one.

Validation

  • python -m pytest tests\test_timeutils.py -q → 6 passed
  • Reverting only boltons\timeutils.py while keeping the new regression tests → 2 failed, 4 passed (the tests genuinely fail without the fix)
  • python -m pytest → 447 passed in 7.21s
  • No configured lint command was found in pyproject.toml, setup.cfg, or tox.ini.

Honor datetime.fold for ambiguous US DST transition times and set fold during UTC conversions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

1 participant