{"record":{"id":"1b5f57a21184a32b","repo":"python/cpython","slug":"inconsistent-use-of-dash-separator","errorCode":null,"errorMessage":"Inconsistent use of dash separator","messagePattern":"Inconsistent use of dash separator","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pydatetime.py","lineNumber":376,"sourceCode":"def _parse_isoformat_date(dtstr):\n    # It is assumed that this is an ASCII-only string of lengths 7, 8 or 10,\n    # see the comment on Modules/_datetimemodule.c:_find_isoformat_datetime_separator\n    if len(dtstr) not in (7, 8, 10):\n        raise ValueError(\"Invalid isoformat string\")\n    year = int(dtstr[0:4])\n    has_sep = dtstr[4] == '-'\n\n    pos = 4 + has_sep\n    if dtstr[pos:pos + 1] == \"W\":\n        # YYYY-?Www-?D?\n        pos += 1\n        weekno = int(dtstr[pos:pos + 2])\n        pos += 2\n\n        dayno = 1\n        if len(dtstr) > pos:\n            if (dtstr[pos:pos + 1] == '-') != has_sep:\n                raise ValueError(\"Inconsistent use of dash separator\")\n\n            pos += has_sep\n\n            dayno = int(dtstr[pos:pos + 1])\n\n        return list(_isoweek_to_gregorian(year, weekno, dayno))\n    else:\n        month = int(dtstr[pos:pos + 2])\n        pos += 2\n        if (dtstr[pos:pos + 1] == \"-\") != has_sep:\n            raise ValueError(\"Inconsistent use of dash separator\")\n\n        pos += has_sep\n        day = int(dtstr[pos:pos + 2])\n\n        return [year, month, day]\n\n","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pydatetime.py#L358-L394","documentation":"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').","triggerScenarios":"datetime.fromisoformat('2021-W535'); '2021W53-5'; strings assembled by conditionally joining parts with '-' in one place and '' in another.","commonSituations":"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.","solutions":["Pick one style and apply it to both separators: '2021-W53-5' or '2021W535'","Construct week dates via date(y, m, d).isocalendar()/isoformat or date.fromisocalendar instead of string assembly","Add a unit test that round-trips your generator through fromisoformat"],"exampleFix":"// before\ns = f\"{y}-W{w:02d}{d}\"  # mixes separated and compact\ndt = datetime.fromisoformat(s)  # ValueError\n\n# after\ns = f\"{y}-W{w:02d}-{d}\"\ndt = datetime.fromisoformat(s)","handlingStrategy":"validation","validationCode":"def norm_week_date(s: str) -> str:\n    # force fully separated form\n    return s if len(s) == 10 else f'{s[:5]}{s[5:7]}-{s[7:]}' if 8 <= len(s) <= 9 else s","typeGuard":"def has_consistent_week_separators(s: str) -> bool:\n    sep_year = s[4:5] == '-'\n    return (s[7:8] == '-') == sep_year if len(s) >= 8 else True","tryCatchPattern":null,"preventionTips":["Generate week dates from date(y,m,d).isocalendar(), never concatenation","Standardize on one separator style project-wide","Assert s.count('-') in (0, 3) for separated week dates before parsing"],"tags":["datetime","fromisoformat","iso-week","separator","valueerror","stdlib"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}