python/cpython · error · TypeError
offset must be a timedelta
Error message
offset must be a timedelta
What it means
timezone.__new__ requires its first argument to be a timedelta instance; it represents a fixed UTC offset as an exact duration. Passing an int (minutes/seconds ambiguity), a string, or None is rejected immediately with TypeError.
Source
Thrown at Lib/_pydatetime.py:2454
THURSDAY = 3
firstday = _ymd2ord(year, 1, 1)
firstweekday = (firstday + 6) % 7 # See weekday() above
week1monday = firstday - firstweekday
if firstweekday > THURSDAY:
week1monday += 7
return week1monday
class timezone(tzinfo):
"""Fixed offset from UTC implementation of tzinfo."""
__slots__ = '_offset', '_name'
# Sentinel value to disallow None
_Omitted = object()
def __new__(cls, offset, name=_Omitted):
if not isinstance(offset, timedelta):
raise TypeError("offset must be a timedelta")
if name is cls._Omitted:
if not offset:
return cls.utc
name = None
elif not isinstance(name, str):
raise TypeError("name must be a string")
if not cls._minoffset <= offset <= cls._maxoffset:
raise ValueError("offset must be a timedelta "
"strictly between -timedelta(hours=24) and "
f"timedelta(hours=24), not {offset!r}")
return cls._create(offset, name)
def __init_subclass__(cls):
raise TypeError("type 'datetime.timezone' is not an acceptable base type")
@classmethod
def _create(cls, offset, name=None):
self = tzinfo.__new__(cls)View on GitHub (pinned to bc6749cc3b)
Solutions
- Wrap the numeric seconds: timezone(timedelta(seconds=7200))
- For minute-based configs: timezone(timedelta(minutes=offset_minutes))
- For named IANA zones use ZoneInfo('Region/City') instead of timezone()
- Type-check config values at load time and convert to timedelta there
Example fix
// before tz = timezone(-5 * 3600) # intended UTC-5 # after tz = timezone(timedelta(hours=-5))
Defensive patterns
Strategy: type-guard
Validate before calling
from datetime import timedelta, timezone
def make_timezone(offset) -> timezone:
if isinstance(offset, int): # seconds, dateutil-style
offset = timedelta(seconds=offset)
if not isinstance(offset, timedelta):
raise TypeError('offset must be int seconds or timedelta')
return timezone(offset) Type guard
from datetime import timedelta
def is_timedelta(v) -> bool:
return isinstance(v, timedelta) Prevention
- Convert numeric offsets to timedelta at config load
- Prefer ZoneInfo for named zones
- Annotate APIs as taking timedelta
When it happens
Trigger: timezone(7200) intending seconds; timezone('-05:00'); timezone(None); timezone(5, 'EST') copying a textbook example in a language where ints worked.
Common situations: Porting code from dateutil.tz.tzoffset('name', seconds) which does accept ints; reading offset configs as numbers of seconds/minutes; timezone-aware ORM fields feeding ints into timezone().
Related errors
- tz argument must be an instance of tzinfo
- cannot compare naive and aware datetimes
- cannot mix naive and timezone-aware time
- name must be a string
- type 'datetime.timezone' is not an acceptable base type
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/4a609f8773b1d0a0.
Report an issue: GitHub.