{"record":{"id":"f4ed817f1490063a","repo":"python/cpython","slug":"month-must-be-in-1-12-not-month","errorCode":null,"errorMessage":"month must be in 1..12, not {month}","messagePattern":"month must be in 1\\.\\.12, not (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pydatetime.py","lineNumber":575,"sourceCode":"    assert name in (\"utcoffset\", \"dst\")\n    if offset is None:\n        return\n    if not isinstance(offset, timedelta):\n        raise TypeError(f\"tzinfo.{name}() must return None \"\n                        f\"or timedelta, not {type(offset).__name__!r}\")\n    if not -timedelta(1) < offset < timedelta(1):\n        raise ValueError(\"offset must be a timedelta \"\n                         \"strictly between -timedelta(hours=24) and \"\n                         f\"timedelta(hours=24), not {offset!r}\")\n\ndef _check_date_fields(year, month, day):\n    year = _index(year)\n    month = _index(month)\n    day = _index(day)\n    if not MINYEAR <= year <= MAXYEAR:\n        raise ValueError(f\"year must be in {MINYEAR}..{MAXYEAR}, not {year}\")\n    if not 1 <= month <= 12:\n        raise ValueError(f\"month must be in 1..12, not {month}\")\n    dim = _days_in_month(year, month)\n    if not 1 <= day <= dim:\n        raise ValueError(f\"day {day} must be in range 1..{dim} for month {month} in year {year}\")\n    return year, month, day\n\ndef _check_time_fields(hour, minute, second, microsecond, fold):\n    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}\")","sourceCodeStart":557,"sourceCodeEnd":593,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pydatetime.py#L557-L593","documentation":"Raised by _check_date_fields() when the month argument to date()/datetime() is not an integer in 1..12. The argument is coerced via __index__ first, so 13, 0, or negative values fail after coercion. This is the standard calendar-range guard for the month field.","triggerScenarios":"date(2024, 13, 1); date(2024, 0, 5); passing a 0-based month from another API (e.g. JavaScript Date getMonth() returns 0..11) directly to Python's date().","commonSituations":"Porting JS/Java code where months are 0-based; off-by-one after parsing month strings with a custom map; user-supplied form input like month=13.","solutions":["Convert 0-based months to 1-based (add 1) before constructing date","Validate month in 1..12 when accepting user input","Use dateutil.parser or datetime.strptime('%Y-%m-%d') to parse instead of manual splitting"],"exampleFix":"// before\nd = date(2024, js_month, 1)  # js_month is 0..11\n// after\nd = date(2024, js_month + 1, 1)","handlingStrategy":"validation","validationCode":"if not 1 <= month <= 12:\n    raise ValueError('month must be 1..12')","typeGuard":"def valid_month(m) -> bool:\n    return 1 <= m <= 12","tryCatchPattern":null,"preventionTips":["Remember Python months are 1-based unlike JavaScript's 0-based getMonth()","Prefer strptime('%Y-%m-%d') over manual field splitting"],"tags":["datetime","valueerror","validation","date"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}