python/cpython · error · TypeError
tzinfo argument must be None or of a tzinfo subclass, not {t
Error message
tzinfo argument must be None or of a tzinfo subclass, not {type(tz).__name__!r} What it means
Raised by _check_tzinfo_arg() when the tz argument to datetime()/time()/their constructors is neither None nor an instance of datetime.tzinfo. Datetime deliberately accepts only tzinfo subclasses (including timezone and zoneinfo.ZoneInfo); passing a string zone name or a module is rejected.
Source
Thrown at Lib/_pydatetime.py:600
hour = _index(hour)
minute = _index(minute)
second = _index(second)
microsecond = _index(microsecond)
if not 0 <= hour <= 23:
raise ValueError(f"hour must be in 0..23, not {hour}")
if not 0 <= minute <= 59:
raise ValueError(f"minute must be in 0..59, not {minute}")
if not 0 <= second <= 59:
raise ValueError(f"second must be in 0..59, not {second}")
if not 0 <= microsecond <= 999999:
raise ValueError(f"microsecond must be in 0..999999, not {microsecond}")
if fold not in (0, 1):
raise ValueError(f"fold must be either 0 or 1, not {fold}")
return hour, minute, second, microsecond, fold
def _check_tzinfo_arg(tz):
if tz is not None and not isinstance(tz, tzinfo):
raise TypeError(
"tzinfo argument must be None or of a tzinfo subclass, "
f"not {type(tz).__name__!r}"
)
def _divide_and_round(a, b):
"""divide a by b and round result to the nearest integer
When the ratio is exactly half-way between two integers,
the even integer is returned.
"""
# Based on the reference implementation for divmod_near
# in Objects/longobject.c.
q, r = divmod(a, b)
# round up if either r / b > 0.5, or r / b == 0.5 and q is odd.
# The expression r / b > 0.5 is equivalent to 2 * r > b if b is
# positive, 2 * r < b if b negative.
r *= 2
greater_than_half = r > b if b > 0 else r < bView on GitHub (pinned to bc6749cc3b)
Solutions
- Use timezone.utc or ZoneInfo('America/New_York') instead of a string
- Assign after construction: dt = dt.replace(tzinfo=ZoneInfo(name))
- Wrap user-supplied zone strings: tzinfo=ZoneInfo(tz) with a try/except ZoneInfoNotFoundError
Example fix
// before dt = datetime(2024, 1, 1, tzinfo='UTC') # TypeError // after from datetime import timezone dt = datetime(2024, 1, 1, tzinfo=timezone.utc)
Defensive patterns
Strategy: type-guard
Validate before calling
from datetime import tzinfo
if tz is not None and not isinstance(tz, tzinfo):
from zoneinfo import ZoneInfo
tz = ZoneInfo(str(tz)) # accept IANA name strings explicitly Type guard
from datetime import tzinfo
def valid_tzarg(tz) -> bool:
return tz is None or isinstance(tz, tzinfo) Prevention
- Pass timezone.utc or ZoneInfo(name), never a bare string
- Wrap user zone names: ZoneInfo(name) with ZoneInfoNotFoundError handling
When it happens
Trigger: datetime(2024, 1, 1, tzinfo='UTC'); dt.astimezone('Europe/Paris'); passing a pytz timezone object works (it subclasses tzinfo) but passing the string 'UTC' or the zoneinfo module itself does not.
Common situations: Expecting datetime() to accept IANA names like datetime(..., tz='America/New_York'); passing tz='UTC' copied from other frameworks (e.g. pandas accepts 'UTC'); migration from libraries that take string zones.
Related errors
- tzinfo.tzname() must return None or string, not {type(name).
- tzinfo.{name}() must return None or timedelta, not {type(off
- offset must be a timedelta strictly between -timedelta(hours
- fromutc() requires a datetime argument
- Malformed time zone string
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/b90cc8f14fc7d0c1.
Report an issue: GitHub.