RustPython/RustPython · error · NotImplementedError
tzinfo subclass must override tzname()
Error message
tzinfo subclass must override tzname()
What it means
tzinfo is an abstract base class: its tzname(), utcoffset() and dst() methods exist only to be overridden, and the base implementations raise NotImplementedError. This error means a bare tzinfo instance (or an incomplete subclass) was attached to a time/datetime and something asked it for a time-zone name via tzname(), directly or through strftime('%Z'). Use a concrete implementation such as datetime.timezone, zoneinfo.ZoneInfo, or a complete custom subclass.
Source
Thrown at Lib/_pydatetime.py:1301
return (self.__class__, self._getstate())
_date_class = date # so functions w/ args named "date" can get at the class
date.min = date(1, 1, 1)
date.max = date(9999, 12, 31)
date.resolution = timedelta(days=1)
class tzinfo:
"""Abstract base class for time zone info classes.
Subclasses must override the tzname(), utcoffset() and dst() methods.
"""
__slots__ = ()
def tzname(self, dt):
"datetime -> string name of time zone."
raise NotImplementedError("tzinfo subclass must override tzname()")
def utcoffset(self, dt):
"datetime -> timedelta, positive for east of UTC, negative for west of UTC"
raise NotImplementedError("tzinfo subclass must override utcoffset()")
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")View on GitHub (pinned to aaeab4f754)
Solutions
- Replace the bare tzinfo with a concrete zone: timezone.utc, timezone(timedelta(hours=n)), or zoneinfo.ZoneInfo('Region/City').
- If it is your own subclass, implement tzname(self, dt) returning the display string (e.g. 'EST' or '+05:00').
- For naive datetimes pass tzinfo=None instead of a dummy tzinfo.
- Audit custom tzinfo classes to confirm all three of tzname/utcoffset/dst are overridden.
Example fix
// before from datetime import time, tzinfo t = time(9, 30, tzinfo=tzinfo()) # later t.tzname() -> NotImplementedError // after from datetime import time, timedelta, timezone t = time(9, 30, tzinfo=timezone(timedelta(hours=5))) print(t.tzname()) # 'UTC+05:00'
Defensive patterns
Strategy: type-guard
Type guard
from datetime import tzinfo
def has_concrete_tzname(tz) -> bool:
if tz is None:
return True
if not isinstance(tz, tzinfo):
return False
try:
tz.tzname(None)
except NotImplementedError:
return False
return True Try / catch
try:
name = dt.tzname()
except NotImplementedError:
name = None # or reattach timezone.utc / ZoneInfo before formatting Prevention
- Never instantiate the abstract tzinfo directly.
- Prefer datetime.timezone or zoneinfo.ZoneInfo over hand-rolled subclasses.
- When subclassing tzinfo, override tzname, utcoffset and dst together.
- Assert tz is None or a known concrete type before attaching it.
When it happens
Trigger: time(12, 0, tzinfo=tzinfo()).tzname(); datetime(..., tzinfo=tzinfo()).strftime('%Z'); a custom tzinfo subclass that overrides utcoffset() and dst() but not tzname(); a stub/mock tz left attached in place of the real zone.
Common situations: Placeholder tzinfo used while wiring up configuration; partial ports from pytz where the old class only implemented offsets; test doubles subclassing tzinfo with just enough to construct; tutorial code copied with tzinfo=tzinfo().
Related errors
- tzinfo subclass must override utcoffset()
- tzinfo subclass must override dst()
- tzinfo.tzname() must return None or string, not {type(name).
- tzinfo.{name}() must return None or timedelta, not {type(off
- tzinfo argument must be None or of a tzinfo subclass, not {t
AI-assisted analysis of RustPython/RustPython@aaeab4f754 (2026-08-17).
Data as JSON: /api/errors/f4bfe315c6c0990d.
Report an issue: GitHub.