{"record":{"id":"21cee14f6a74929b","repo":"python/cpython","slug":"invalid-week-week","errorCode":null,"errorMessage":"Invalid week: {week}","messagePattern":"Invalid week: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pydatetime.py","lineNumber":529,"sourceCode":"# tuple[int, int, int] -> tuple[int, int, int] version of date.fromisocalendar\ndef _isoweek_to_gregorian(year, week, day):\n    # Year is bounded this way because 9999-12-31 is (9999, 52, 5)\n    if not MINYEAR <= year <= MAXYEAR:\n        raise ValueError(f\"year must be in {MINYEAR}..{MAXYEAR}, not {year}\")\n\n    if not 0 < week < 53:\n        out_of_range = True\n\n        if week == 53:\n            # ISO years have 53 weeks in them on years starting with a\n            # Thursday and leap years starting on a Wednesday\n            first_weekday = _ymd2ord(year, 1, 1) % 7\n            if (first_weekday == 4 or (first_weekday == 3 and\n                                       _is_leap(year))):\n                out_of_range = False\n\n        if out_of_range:\n            raise ValueError(f\"Invalid week: {week}\")\n\n    if not 0 < day < 8:\n        raise ValueError(f\"Invalid weekday: {day} (range is [1, 7])\")\n\n    # Now compute the offset from (Y, 1, 1) in days:\n    day_offset = (week - 1) * 7 + (day - 1)\n\n    # Calculate the ordinal day for monday, week 1\n    day_1 = _isoweek1monday(year)\n    ord_day = day_1 + day_offset\n\n    return _ord2ymd(ord_day)\n\n\n# Just raise TypeError if the arg isn't None or a string.\ndef _check_tzname(name):\n    if name is not None and not isinstance(name, str):\n        raise TypeError(\"tzinfo.tzname() must return None or string, \"","sourceCodeStart":511,"sourceCodeEnd":547,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pydatetime.py#L511-L547","documentation":"ISO week numbers must be 1..52, or 53 only in long ISO years (those starting on a Thursday, or leap years starting on a Wednesday — checked via _ymd2ord(year,1,1) % 7). Week 0, week 53 in a short year, or weeks > 53 raise ValueError('Invalid week: N').","triggerScenarios":"date.fromisocalendar(2021, 53, 1) (2021 has 52 ISO weeks); fromisocalendar(2021, 0, 1); week computed as last_week + 1 rolling past year end without incrementing the ISO year.","commonSituations":"Off-by-one when iterating weeks across year boundaries; user input assuming every year has 53 weeks; reporting software that increments week without checking date.isocalendar() of Dec 28 (the week-count pivot); week 53 hard-coded for fiscal calendars.","solutions":["Derive the max week from the calendar itself: max_week = date(y, 12, 28).isocalendar()[1] and validate against it","When incrementing weeks, recompute from the resulting date: d += timedelta(weeks=1); y, w, dd = d.isocalendar()","Reject week 0 and week 53 early unless the long-year check passes"],"exampleFix":"// before\nd = date.fromisocalendar(2021, 53, 1)  # ValueError: 2021 has 52 weeks\n\n# after\nfrom datetime import date, timedelta\nd = date(2021, 1, 4) + timedelta(weeks=52)  # step from a known week-1 Monday\n# or validate: assert week <= date(year, 12, 28).isocalendar()[1]","handlingStrategy":"validation","validationCode":"from datetime import date\ndef max_iso_week(year: int) -> int:\n    return date(year, 12, 28).isocalendar()[1]  # Dec 28 is always in the last week\ndef check_week(year: int, week: int) -> None:\n    if not 1 <= week <= max_iso_week(year):\n        raise ValueError(f'week {week} invalid for {year} (max {max_iso_week(year)})')","typeGuard":"def is_valid_iso_week(year: int, week: int) -> bool:\n    return 1 <= week <= date(year, 12, 28).isocalendar()[1]","tryCatchPattern":"try:\n    d = date.fromisocalendar(y, w, wd)\nexcept ValueError:\n    d = None  # clamp/skip and log the offending record","preventionTips":["Never assume 53 weeks; compute the year's max via Dec 28","When rolling weeks forward, recompute y/w from the resulting date","Validate week 0 from external input early"],"tags":["datetime","isocalendar","fromisocalendar","iso-week","valueerror","stdlib"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}