{"record":{"id":"92ef4e6c27f37154","repo":"TheAlgorithms/Python","slug":"date-must-be-between-1-31","errorCode":null,"errorMessage":"Date must be between 1 - 31","messagePattern":"Date must be between 1 - 31","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"maths/zellers_congruence.py","lineNumber":106,"sourceCode":"    if not 0 < len(date_input) < 11:\n        raise ValueError(\"Must be 10 characters long\")\n\n    # Get month\n    m: int = int(date_input[0] + date_input[1])\n    # Validate\n    if not 0 < m < 13:\n        raise ValueError(\"Month must be between 1 - 12\")\n\n    sep_1: str = date_input[2]\n    # Validate\n    if sep_1 not in [\"-\", \"/\"]:\n        raise ValueError(\"Date separator must be '-' or '/'\")\n\n    # Get day\n    d: int = int(date_input[3] + date_input[4])\n    # Validate\n    if not 0 < d < 32:\n        raise ValueError(\"Date must be between 1 - 31\")\n\n    # Get second separator\n    sep_2: str = date_input[5]\n    # Validate\n    if sep_2 not in [\"-\", \"/\"]:\n        raise ValueError(\"Date separator must be '-' or '/'\")\n\n    # Get year\n    y: int = int(date_input[6] + date_input[7] + date_input[8] + date_input[9])\n    # Arbitrary year range\n    if not 45 < y < 8500:\n        raise ValueError(\n            \"Year out of range. There has to be some sort of limit...right?\"\n        )\n\n    # Get datetime obj for validation\n    dt_ck = datetime.date(int(y), int(m), int(d))\n","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/maths/zellers_congruence.py#L88-L124","documentation":"Raised by zeller(date_input) in maths/zellers_congruence.py when the two-digit day parsed from date_input[3:5] is not in 1..31. Like the other checks it is positional, so any upstream misalignment (wrong separator count, missing zero padding) can surface here as an out-of-range day. Note the function later cross-checks the real calendar with datetime.date(y, m, d), so impossible days like 02-31 also fail, though with datetime's own ValueError.","triggerScenarios":"Calling zeller('01-33-2010') (day 33); passing DD-MM-YYYY input where the day lands in the month slot or vice versa; '01-.4-2010' where the day is non-numeric raises int() ValueError instead.","commonSituations":"Day/month transposition; unpadded single-digit days shifting positions ('1-3-2010'); user typos or scraped text with malformed dates.","solutions":["Normalize to MM-DD-YYYY via strftime('%m-%d-%Y') so the day is always valid and correctly positioned.","Validate input with datetime.strptime(s, '%m-%d-%Y') before calling zeller to get a precise, well-known error message.","If accepting multiple formats, parse to a date object first, then format to the one shape zeller accepts."],"exampleFix":"# before\nzeller(raw)  # raw = '31-01-2010' style or malformed\n\n# after\nfrom datetime import datetime\nd = datetime.strptime(raw, '%d-%m-%Y')  # parse what you actually receive\nzeller(d.strftime('%m-%d-%Y'))","handlingStrategy":"validation","validationCode":"from datetime import datetime\n\ndef valid_mmddyyyy(s: str) -> bool:\n    try:\n        datetime.strptime(s, '%m-%d-%Y')\n        return True\n    except ValueError:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    day = zeller(s)\nexcept ValueError as e:\n    # covers day range plus datetime's own calendar check (e.g. 02-31)\n    return f'invalid date {s!r}: {e}'","preventionTips":["Zero-pad single-digit days and months (the parser is positional).","Validate with strptime('%m-%d-%Y') first for precise messages."],"tags":["date","validation","string-parsing","valueerror"],"backgroundTag":null,"analyzedSha":"f5988cc09713315817df6a7e327e258013a94440","analyzedAt":"2026-08-14T17:30:07.041Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}