python/cpython · error · NotImplementedError
tzinfo subclass must override tzname()
Error message
tzinfo subclass must override tzname()
What it means
Raised by the abstract base tzinfo.tzname() when a timezone subclass does not override it. tzinfo is an interface: tzname(), utcoffset() and dst() must all be implemented by concrete subclasses. This error means someone instantiated/used a tzinfo subclass (including tzinfo itself) that left tzname() unimplemented.
Source
Thrown at Lib/_pydatetime.py:1317
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 objects.
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 bc6749cc3b)
Solutions
- Override tzname(self, dt) in the subclass to return the zone name string (or None)
- Prefer the built-in datetime.timezone or zoneinfo.ZoneInfo instead of a hand-rolled tzinfo subclass
- If the method is intentionally unsupported, return None rather than inheriting the abstract stub
Example fix
// before
class MyTZ(tzinfo):
def utcoffset(self, dt): return timedelta(hours=5)
def dst(self, dt): return timedelta(0)
// after
class MyTZ(tzinfo):
def utcoffset(self, dt): return timedelta(hours=5)
def dst(self, dt): return timedelta(0)
def tzname(self, dt): return 'UTC+05' Defensive patterns
Strategy: validation
Validate before calling
for m in ('tzname', 'utcoffset', 'dst'):
if type(tz).__getattribute__(type(tz), m) is getattr(tzinfo, m):
raise TypeError(f'{type(tz).__name__} must implement {m}()') Type guard
def is_complete_tzinfo(tz) -> bool:
return all(getattr(type(tz), m, None) is not getattr(tzinfo, m)
for m in ('tzname', 'utcoffset', 'dst')) Try / catch
try:
name = dt.tzname()
except NotImplementedError:
name = None # zone name unavailable; proceed without it Prevention
- Prefer zoneinfo.ZoneInfo or datetime.timezone over custom tzinfo subclasses
- Add an abstract-method test that instantiates your tzinfo subclass and calls all three methods
- Return None instead of inheriting abstract stubs for genuinely unsupported methods
When it happens
Trigger: class MyTZ(tzinfo): pass; then MyTZ().tzname(dt) — or any datetime with tz=MyTZ() calling .tzname(), or strftime('%Z') on such a datetime. Also calling tzinfo().tzname(dt) directly on the base class.
Common situations: Writing a custom timezone class for legacy regional rules and forgetting one of the three required methods; partially copy-pasted tzinfo subclasses from tutorials; migrating from pytz where method names differ.
Related errors
- tzinfo subclass must override utcoffset()
- tzinfo subclass must override dst()
- Malformed time zone string
- tzinfo.tzname() must return None or string, not {type(name).
- tzinfo.{name}() must return None or timedelta, not {type(off
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/d5305f282ed5f50b.
Report an issue: GitHub.