python/cpython · error · ValueError

Invalid weekday: {day} (range is [1, 7])

Error message

Invalid weekday: {day} (range is [1, 7])

What it means

ISO weekday numbers are 1 (Monday) through 7 (Sunday), unlike datetime.isoweekday conventions being the same but user-facing calendars often 0-based. _isoweek_to_gregorian raises ValueError('Invalid weekday: N (range is [1, 7])') for day 0, day 8, or negative values.

Source

Thrown at Lib/_pydatetime.py:532

    if not MINYEAR <= year <= MAXYEAR:
        raise ValueError(f"year must be in {MINYEAR}..{MAXYEAR}, not {year}")

    if not 0 < week < 53:
        out_of_range = True

        if week == 53:
            # ISO years have 53 weeks in them on years starting with a
            # Thursday and leap years starting on a Wednesday
            first_weekday = _ymd2ord(year, 1, 1) % 7
            if (first_weekday == 4 or (first_weekday == 3 and
                                       _is_leap(year))):
                out_of_range = False

        if out_of_range:
            raise ValueError(f"Invalid week: {week}")

    if not 0 < day < 8:
        raise ValueError(f"Invalid weekday: {day} (range is [1, 7])")

    # Now compute the offset from (Y, 1, 1) in days:
    day_offset = (week - 1) * 7 + (day - 1)

    # Calculate the ordinal day for monday, week 1
    day_1 = _isoweek1monday(year)
    ord_day = day_1 + day_offset

    return _ord2ymd(ord_day)


# Just raise TypeError if the arg isn't None or a string.
def _check_tzname(name):
    if name is not None and not isinstance(name, str):
        raise TypeError("tzinfo.tzname() must return None or string, "
                        f"not {type(name).__name__!r}")

# name is the offset-producing method, "utcoffset" or "dst".

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Convert 0-based days: iso_day = zero_based + 1 (verify the source convention first)
  2. Prefer deriving dates via timedelta from a known Monday instead of manual weekday arithmetic
  3. Validate 1 <= day <= 7 before calling fromisocalendar

Example fix

// before
dow = some_date.weekday()            # 0..6
d = date.fromisocalendar(y, w, dow)  # ValueError when dow == 0

# after
dow = some_date.isoweekday()         # 1..7
d = date.fromisocalendar(y, w, dow)
Defensive patterns

Strategy: validation

Validate before calling

def check_iso_weekday(day: int) -> None:
    if not 1 <= day <= 7:
        raise ValueError(f'ISO weekday must be 1..7, got {day}')

Type guard

def is_valid_iso_weekday(d: object) -> bool:
    return isinstance(d, int) and 1 <= d <= 7

Prevention

When it happens

Trigger: date.fromisocalendar(2021, 5, 0); passing a Python date.weekday() result (0..6, Monday=0) where an ISO weekday (1..7) is expected; arrays indexed 0-based fed component-wise into fromisocalendar.

Common situations: Confusing date.weekday() (0-6) with date.isoweekday() (1-7); JavaScript/Java weekday conventions crossing into Python; cron-like 0-based day fields reused for ISO weeks.

Related errors


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