python/cpython · error · TypeError

type 'datetime.timezone' is not an acceptable base type

Error message

type 'datetime.timezone' is not an acceptable base type

What it means

datetime.timezone (like datetime, date, time, and timedelta) disallows subclassing by defining __init_subclass__ to raise TypeError. The class is treated as a concrete builtin-style type; its C twin has the same restriction. Use composition or subclass the generic tzinfo base instead.

Source

Thrown at Lib/_pydatetime.py:2468

    # 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)
        self._offset = offset
        self._name = name
        return self

    def __getinitargs__(self):
        """pickle support"""
        if self._name is None:
            return (self._offset,)
        return (self._offset, self._name)

    def __eq__(self, other):
        if isinstance(other, timezone):
            return self._offset == other._offset
        return NotImplemented

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Subclass tzinfo directly and implement utcoffset/tzname/dst/fromutc
  2. Or wrap a timezone instance in your own class (composition) and delegate
  3. For varying rules use zoneinfo.ZoneInfo instead of subclassing

Example fix

// before
class BusinessTZ(timezone): ...

# after
from datetime import tzinfo
class BusinessTZ(tzinfo):
    def utcoffset(self, dt): return timedelta(hours=9)
    def tzname(self, dt): return 'BUS'
    def dst(self, dt): return None
Defensive patterns

Strategy: type-guard

Validate before calling

from datetime import timezone, tzinfo

def timezone_like_base(cls):
    return tzinfo if cls is timezone else cls

Type guard

from datetime import timezone

def is_subclassable(cls) -> bool:
    return not hasattr(cls, '__init_subclass__') or cls.__init_subclass__ is object.__init_subclass__

Prevention

When it happens

Trigger: class MyTZ(timezone): ...; attempting collections.namedtuple-style extension; metaclass frameworks (Django/SQLAlchemy custom types, ORMs) that auto-derive from base classes including timezone.

Common situations: Trying to add a display name table or DST behavior on top of fixed-offset timezone; plugin systems that subclass whatever type they receive; copy-paste from tzinfo examples applied to timezone.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/5f7e93dbc18cbe5a. Report an issue: GitHub.