RustPython/RustPython · error · ValueError
fromutc() requires a non-None utcoffset() result
Error message
fromutc() requires a non-None utcoffset() result
What it means
The fromutc() algorithm needs dt.utcoffset() to compute the gap between UTC and the zone's standard time. If the attached tzinfo answers None — the convention for 'offset unknown', and what broken or half-implemented zones return — the conversion cannot proceed and raises this ValueError.
Source
Thrown at Lib/_pydatetime.py:1325
def dst(self, dt):
"""datetime -> DST offset as timedelta, positive for east of UTC.
Return 0 if DST not in effect. utcoffset() must include the DST
offset.
"""
raise NotImplementedError("tzinfo subclass must override dst()")
def fromutc(self, dt):
"datetime in UTC -> datetime in local time."
if not isinstance(dt, datetime):
raise TypeError("fromutc() requires a datetime argument")
if dt.tzinfo is not self:
raise ValueError("dt.tzinfo is not self")
dtoff = dt.utcoffset()
if dtoff is None:
raise ValueError("fromutc() requires a non-None utcoffset() "
"result")
# See the long comment block at the end of this file for an
# explanation of this algorithm.
dtdst = dt.dst()
if dtdst is None:
raise ValueError("fromutc() requires a non-None dst() result")
delta = dtoff - dtdst
if delta:
dt += delta
dtdst = dt.dst()
if dtdst is None:
raise ValueError("fromutc(): dt.dst gave inconsistent "
"results; cannot convert")
return dt + dtdst
# Pickle support.
View on GitHub (pinned to aaeab4f754)
Solutions
- Use astimezone() with concrete zones (datetime.timezone, zoneinfo) that always report an offset.
- Make the custom utcoffset() return a timedelta for every datetime fromutc() will see; reserve None strictly for 'unknown'.
- Check dt.utcoffset() is not None before calling tz.fromutc(dt).
Example fix
// before
result = my_tz.fromutc(dt) # my_tz.utcoffset(dt) returned None
// after
if dt.utcoffset() is None:
raise ValueError(f'{my_tz!r} reports no offset for {dt}')
result = dt.astimezone(my_tz) Defensive patterns
Strategy: validation
Validate before calling
def fromutc_safe(tz, dt):
if dt.tzinfo is not tz:
dt = dt.replace(tzinfo=tz)
if dt.utcoffset() is None:
raise ValueError(f'{tz!r} reports no utcoffset for {dt}')
return tz.fromutc(dt) Try / catch
try:
local = tz.fromutc(dt)
except ValueError:
local = dt.replace(tzinfo=timezone.utc).astimezone(tz) # concrete-zone fallback Prevention
- Verify dt.utcoffset() is not None before calling fromutc().
- Custom utcoffset() should return a timedelta, reserving None for 'unknown'.
- Prefer timezone/zoneinfo zones that always report offsets.
When it happens
Trigger: tz.fromutc(dt) where dt.tzinfo.utcoffset(dt) returns None; a custom tzinfo whose utcoffset() has a None code path for some datetimes; zones that refuse offsets for pre-transition or ambiguous times.
Common situations: Custom tzinfo subclasses modeled on doc examples where utcoffset returns None by default; pipelines attaching half-implemented zones; porting code that assumed an offset always exists for aware datetimes.
Related errors
- dt.tzinfo is not self
- fromutc() requires a non-None dst() result
- fromutc(): dt.dst gave inconsistent results; cannot convert
- fromutc: dt.tzinfo is not self
- tzinfo.{name}() must return None or timedelta, not {type(off
AI-assisted analysis of RustPython/RustPython@aaeab4f754 (2026-08-17).
Data as JSON: /api/errors/03597db1c23a126c.
Report an issue: GitHub.