{"record":{"id":"5f7e93dbc18cbe5a","repo":"python/cpython","slug":"type-datetime-timezone-is-not-an-acceptable-base","errorCode":null,"errorMessage":"type 'datetime.timezone' is not an acceptable base type","messagePattern":"type 'datetime\\.timezone' is not an acceptable base type","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/_pydatetime.py","lineNumber":2468,"sourceCode":"    # Sentinel value to disallow None\n    _Omitted = object()\n    def __new__(cls, offset, name=_Omitted):\n        if not isinstance(offset, timedelta):\n            raise TypeError(\"offset must be a timedelta\")\n        if name is cls._Omitted:\n            if not offset:\n                return cls.utc\n            name = None\n        elif not isinstance(name, str):\n            raise TypeError(\"name must be a string\")\n        if not cls._minoffset <= offset <= cls._maxoffset:\n            raise ValueError(\"offset must be a timedelta \"\n                             \"strictly between -timedelta(hours=24) and \"\n                             f\"timedelta(hours=24), not {offset!r}\")\n        return cls._create(offset, name)\n\n    def __init_subclass__(cls):\n        raise TypeError(\"type 'datetime.timezone' is not an acceptable base type\")\n\n    @classmethod\n    def _create(cls, offset, name=None):\n        self = tzinfo.__new__(cls)\n        self._offset = offset\n        self._name = name\n        return self\n\n    def __getinitargs__(self):\n        \"\"\"pickle support\"\"\"\n        if self._name is None:\n            return (self._offset,)\n        return (self._offset, self._name)\n\n    def __eq__(self, other):\n        if isinstance(other, timezone):\n            return self._offset == other._offset\n        return NotImplemented","sourceCodeStart":2450,"sourceCodeEnd":2486,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pydatetime.py#L2450-L2486","documentation":"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.","triggerScenarios":"class MyTZ(timezone): ...; attempting collections.namedtuple-style extension; metaclass frameworks (Django/SQLAlchemy custom types, ORMs) that auto-derive from base classes including timezone.","commonSituations":"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.","solutions":["Subclass tzinfo directly and implement utcoffset/tzname/dst/fromutc","Or wrap a timezone instance in your own class (composition) and delegate","For varying rules use zoneinfo.ZoneInfo instead of subclassing"],"exampleFix":"// before\nclass BusinessTZ(timezone): ...\n\n# after\nfrom datetime import tzinfo\nclass BusinessTZ(tzinfo):\n    def utcoffset(self, dt): return timedelta(hours=9)\n    def tzname(self, dt): return 'BUS'\n    def dst(self, dt): return None","handlingStrategy":"type-guard","validationCode":"from datetime import timezone, tzinfo\n\ndef timezone_like_base(cls):\n    return tzinfo if cls is timezone else cls","typeGuard":"from datetime import timezone\n\ndef is_subclassable(cls) -> bool:\n    return not hasattr(cls, '__init_subclass__') or cls.__init_subclass__ is object.__init_subclass__","tryCatchPattern":null,"preventionTips":["Subclass tzinfo for custom zones","Use composition to extend timezone behavior","Remember all datetime-family types are final"],"tags":["python","datetime","timezone","type-error","inheritance"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}