python/cpython · error · ValueError

Inconsistent use of dash separator

Error message

Inconsistent use of dash separator

What it means

Inside _parse_isoformat_date, ISO week-date strings must use the dash consistently: if the year is separated from 'Www' by a hyphen (YYYY-Www), the week-to-day separator must also be a hyphen; if compact (YYYYWww), the day must follow compactly. Mixing the two styles (e.g. '2021-W535' or '2021W53-5') raises ValueError('Inconsistent use of dash separator').

Source

Thrown at Lib/_pydatetime.py:376

def _parse_isoformat_date(dtstr):
    # It is assumed that this is an ASCII-only string of lengths 7, 8 or 10,
    # see the comment on Modules/_datetimemodule.c:_find_isoformat_datetime_separator
    if len(dtstr) not in (7, 8, 10):
        raise ValueError("Invalid isoformat string")
    year = int(dtstr[0:4])
    has_sep = dtstr[4] == '-'

    pos = 4 + has_sep
    if dtstr[pos:pos + 1] == "W":
        # YYYY-?Www-?D?
        pos += 1
        weekno = int(dtstr[pos:pos + 2])
        pos += 2

        dayno = 1
        if len(dtstr) > pos:
            if (dtstr[pos:pos + 1] == '-') != has_sep:
                raise ValueError("Inconsistent use of dash separator")

            pos += has_sep

            dayno = int(dtstr[pos:pos + 1])

        return list(_isoweek_to_gregorian(year, weekno, dayno))
    else:
        month = int(dtstr[pos:pos + 2])
        pos += 2
        if (dtstr[pos:pos + 1] == "-") != has_sep:
            raise ValueError("Inconsistent use of dash separator")

        pos += has_sep
        day = int(dtstr[pos:pos + 2])

        return [year, month, day]

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Pick one style and apply it to both separators: '2021-W53-5' or '2021W535'
  2. Construct week dates via date(y, m, d).isocalendar()/isoformat or date.fromisocalendar instead of string assembly
  3. Add a unit test that round-trips your generator through fromisoformat

Example fix

// before
s = f"{y}-W{w:02d}{d}"  # mixes separated and compact
dt = datetime.fromisoformat(s)  # ValueError

# after
s = f"{y}-W{w:02d}-{d}"
dt = datetime.fromisoformat(s)
Defensive patterns

Strategy: validation

Validate before calling

def norm_week_date(s: str) -> str:
    # force fully separated form
    return s if len(s) == 10 else f'{s[:5]}{s[5:7]}-{s[7:]}' if 8 <= len(s) <= 9 else s

Type guard

def has_consistent_week_separators(s: str) -> bool:
    sep_year = s[4:5] == '-'
    return (s[7:8] == '-') == sep_year if len(s) >= 8 else True

Prevention

When it happens

Trigger: datetime.fromisoformat('2021-W535'); '2021W53-5'; strings assembled by conditionally joining parts with '-' in one place and '' in another.

Common situations: Templated string building where separators are injected from a variable applied inconsistently; data migrated between systems with different ISO compaction styles; typos in hand-written test fixtures.

Related errors


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