Maya 0.6.1 silently resolves ambiguous DST fallback times to the first occurrence — how to control or detect this?
0 reputation · 18 Oct 2023, 05:08 UTC
0 reputation · 18 Oct 2023, 05:08 UTC
I'm using Maya 0.6.1 to parse local datetimes in a US/Eastern context and convert them across zones. According to the documented behavior, a naive string parsed with timezone='US/Eastern' that falls in the DST fallback window (e.g., 2023-11-05 01:30) resolves to the first occurrence (EDT) with no warning, and spring-forward gaps raise NonExistentTimeError because Maya doesn't expose pytz's is_dst flag.
Inputs arrive as naive local timestamps from an external system, so I must attach the zone at parse time. I need deterministic handling: pick the second occurrence for ambiguous times, and a defined policy for non-existent times, without post-hoc pytz surgery on every value. I also want to audit which stored values were ambiguous.
Is there any supported way in Maya to influence which occurrence is chosen for ambiguous local times, or to intercept the NonExistentTimeError path cleanly? If not, is wrapping Maya's parse with direct pytz localize(is_dst=...) the accepted workaround, and does that stay compatible with Maya's internal UTC epoch? Finally, is there a reliable pattern to detect after the fact that a parsed value was ambiguous?
31775 reputation · 18 Oct 2023, 13:24 UTC
No — Maya 0.6.1 has no supported way to influence which occurrence is chosen for ambiguous local times, and no hook to intercept the NonExistentTimeError path other than catching it. The silent first-occurrence (EDT) resolution you observed is inherited from pytz's localize() default of is_dst=False... wait, the key detail: pytz's localize() defaults to is_dst=False, but Maya's parsing path effectively resolves ambiguous wall times to the first occurrence and offers no parameter to change it. The accepted workaround is exactly what you suspected: localize with pytz directly, then wrap the aware datetime in Maya. That is fully compatible with Maya's internals because Maya stores everything as a UTC epoch anyway.
A MayaDT is essentially a wrapper around a UTC timestamp. Once a datetime is timezone-aware, Maya only needs its UTC equivalent — it does not care which library produced the awareness. So this round-trips cleanly:
import maya
import pytz
from datetime import datetime
eastern = pytz.timezone('US/Eastern')
naive = datetime(2023, 11, 5, 1, 30)
# Second occurrence (EST) instead of Maya's silent first (EDT)
aware = eastern.localize(naive, is_dst=False)
dt = maya.MayaDT.from_datetime(aware)
print(dt.iso8601()) # 2023-11-05T06:30:00Z, not 05:30:00ZVerify epoch compatibility on your version with a known instant: compare maya.MayaDT.from_datetime(aware).epoch against aware.timestamp(). They should match.
Use is_dst=None, which makes pytz raise on both ambiguous and non-existent times instead of guessing. That gives you one choke point for your policy:
from pytz.exceptions import AmbiguousTimeError, NonExistentTimeError
def parse_local(s, tz):
naive = datetime.strptime(s, '%Y-%m-%d %H:%M')
try:
aware = tz.localize(naive, is_dst=None)
except AmbiguousTimeError:
aware = tz.localize(naive, is_dst=False) # policy: second occurrence
audit_log(s, 'ambiguous')
except NonExistentTimeError:
aware = tz.localize(naive, is_dst=True) # policy: shift forward
audit_log(s, 'gap')
return maya.MayaDT.from_datetime(aware)This replaces both Maya behaviors you dislike: ambiguity becomes an explicit branch, and the gap no longer escapes as an unhandled Maya exception. Keep the localization on naive datetimes only — calling localize() on an already-aware datetime raises ValueError.
If values are stored as UTC (which Maya encourages), you can detect past ambiguity by reversing the conversion: convert each stored UTC instant back to US/Eastern and check whether its wall time falls inside the fallback window (for US/Eastern, 01:00–02:00 local on the transition date). Any stored value whose local wall time is in that window may have been ambiguous — but note the limitation: you cannot tell from the UTC value alone whether the original input intended the first or second occurrence. Detection after the fact tells you which rows were at risk, not which were wrong. Going forward, the audit_log call above is the only reliable record.
Maya is effectively unmaintained, and pytz itself is legacy compared to Python 3.9+'s zoneinfo (which uses a fold attribute instead of is_dst). If this pipeline is long-lived, consider whether Maya is earning its place versus plain zoneinfo datetimes. Also confirm the exact transition-window behavior against your installed pytz version's tzdata, since transition dates are data-driven, not hardcoded.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.