{"record":{"id":"b90cc8f14fc7d0c1","repo":"python/cpython","slug":"tzinfo-argument-must-be-none-or-of-a-tzinfo-subcla","errorCode":null,"errorMessage":"tzinfo argument must be None or of a tzinfo subclass, not {type(tz).__name__!r}","messagePattern":"tzinfo argument must be None or of a tzinfo subclass, not (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/_pydatetime.py","lineNumber":600,"sourceCode":"    hour = _index(hour)\n    minute = _index(minute)\n    second = _index(second)\n    microsecond = _index(microsecond)\n    if not 0 <= hour <= 23:\n        raise ValueError(f\"hour must be in 0..23, not {hour}\")\n    if not 0 <= minute <= 59:\n        raise ValueError(f\"minute must be in 0..59, not {minute}\")\n    if not 0 <= second <= 59:\n        raise ValueError(f\"second must be in 0..59, not {second}\")\n    if not 0 <= microsecond <= 999999:\n        raise ValueError(f\"microsecond must be in 0..999999, not {microsecond}\")\n    if fold not in (0, 1):\n        raise ValueError(f\"fold must be either 0 or 1, not {fold}\")\n    return hour, minute, second, microsecond, fold\n\ndef _check_tzinfo_arg(tz):\n    if tz is not None and not isinstance(tz, tzinfo):\n        raise TypeError(\n            \"tzinfo argument must be None or of a tzinfo subclass, \"\n            f\"not {type(tz).__name__!r}\"\n        )\n\ndef _divide_and_round(a, b):\n    \"\"\"divide a by b and round result to the nearest integer\n\n    When the ratio is exactly half-way between two integers,\n    the even integer is returned.\n    \"\"\"\n    # Based on the reference implementation for divmod_near\n    # in Objects/longobject.c.\n    q, r = divmod(a, b)\n    # round up if either r / b > 0.5, or r / b == 0.5 and q is odd.\n    # The expression r / b > 0.5 is equivalent to 2 * r > b if b is\n    # positive, 2 * r < b if b negative.\n    r *= 2\n    greater_than_half = r > b if b > 0 else r < b","sourceCodeStart":582,"sourceCodeEnd":618,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pydatetime.py#L582-L618","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ndt = datetime(2024, 1, 1, tzinfo='UTC')  # TypeError\n// after\nfrom datetime import timezone\ndt = datetime(2024, 1, 1, tzinfo=timezone.utc)","handlingStrategy":"type-guard","validationCode":"from datetime import tzinfo\n\nif tz is not None and not isinstance(tz, tzinfo):\n    from zoneinfo import ZoneInfo\n    tz = ZoneInfo(str(tz))  # accept IANA name strings explicitly","typeGuard":"from datetime import tzinfo\n\ndef valid_tzarg(tz) -> bool:\n    return tz is None or isinstance(tz, tzinfo)","tryCatchPattern":null,"preventionTips":["Pass timezone.utc or ZoneInfo(name), never a bare string","Wrap user zone names: ZoneInfo(name) with ZoneInfoNotFoundError handling"],"tags":["datetime","typeerror","tzinfo","timezone"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}