python/cpython · error · ValueError

ISO week directive '%V' is incompatible with the year direct

Error message

ISO week directive '%V' is incompatible with the year directive '%Y'. Use the ISO year '%G' instead.

What it means

If %V (ISO week) matched AND a regular year %Y/%y is present AND a weekday is present, all three branches of the ambiguity block are satisfied but mixing calendar year %Y with ISO week %V is wrong: at year boundaries week 1 can belong to the previous/next ISO year. _strptime raises and points to %G.

Source

Thrown at Lib/_strptime.py:750

    # Deal with the cases where ambiguities arise
    # don't assume default values for ISO week/year
    if iso_year is not None:
        if julian is not None:
            raise ValueError("Day of the year directive '%j' is not "
                             "compatible with ISO year directive '%G'. "
                             "Use '%Y' instead.")
        elif iso_week is None or weekday is None:
            raise ValueError("ISO year directive '%G' must be used with "
                             "the ISO week directive '%V' and a weekday "
                             "directive ('%A', '%a', '%w', or '%u').")
    elif iso_week is not None:
        if year is None or weekday is None:
            raise ValueError("ISO week directive '%V' must be used with "
                             "the ISO year directive '%G' and a weekday "
                             "directive ('%A', '%a', '%w', or '%u').")
        else:
            raise ValueError("ISO week directive '%V' is incompatible with "
                             "the year directive '%Y'. Use the ISO year '%G' "
                             "instead.")

    leap_year_fix = False
    if year is None:
        if month == 2 and day == 29:
            year = 1904  # 1904 is first leap year of 20th century
            leap_year_fix = True
        else:
            year = 1900

    # If we know the week of the year and what day of that week, we can figure
    # out the Julian day of the year.
    if julian is None and weekday is not None:
        if week_of_year is not None:
            week_starts_Mon = True if week_of_year_start == 0 else False
            julian = _calc_julian_from_U_or_W(year, week_of_year, weekday,
                                                week_starts_Mon)

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Replace %Y with %G in the format for ISO week dates
  2. If you truly have calendar year + week number (non-ISO semantics), compute the date manually with timedelta arithmetic from Jan 1 instead of strptime

Example fix

# before
>>> datetime.strptime('2020 12 3', '%Y %V %u')
ValueError: ISO week directive '%V' is incompatible with the year directive '%Y'. Use the ISO year '%G' instead.

# after
>>> datetime.strptime('2020 12 3', '%G %V %u')
datetime.datetime(2020, 3, 18, 0, 0)
Defensive patterns

Strategy: validation

Validate before calling

def fix_year_directive(fmt: str) -> str:
    clean = fmt.replace('%%', '')
    if '%V' in clean and '%Y' in clean:
        return fmt.replace('%Y', '%G')
    return fmt

Prevention

When it happens

Trigger: datetime.strptime('2020 12 3', '%Y %V %u') — calendar year paired with ISO week number; typical when '2020-W12-3' style data is parsed with %Y instead of %G.

Common situations: Off-by-one-week bugs around New Year lead developers to ISO weeks; then they keep %Y out of habit. Dates like 2021-01-01 belong to ISO week 53 of ISO year 2020.

Related errors


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