TheAlgorithms/Python · error · ValueError

Date must be between 1 - 31

Error message

Date must be between 1 - 31

What it means

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.

Source

Thrown at maths/zellers_congruence.py:106

    if not 0 < len(date_input) < 11:
        raise ValueError("Must be 10 characters long")

    # Get month
    m: int = int(date_input[0] + date_input[1])
    # Validate
    if not 0 < m < 13:
        raise ValueError("Month must be between 1 - 12")

    sep_1: str = date_input[2]
    # Validate
    if sep_1 not in ["-", "/"]:
        raise ValueError("Date separator must be '-' or '/'")

    # Get day
    d: int = int(date_input[3] + date_input[4])
    # Validate
    if not 0 < d < 32:
        raise ValueError("Date must be between 1 - 31")

    # Get second separator
    sep_2: str = date_input[5]
    # Validate
    if sep_2 not in ["-", "/"]:
        raise ValueError("Date separator must be '-' or '/'")

    # Get year
    y: int = int(date_input[6] + date_input[7] + date_input[8] + date_input[9])
    # Arbitrary year range
    if not 45 < y < 8500:
        raise ValueError(
            "Year out of range. There has to be some sort of limit...right?"
        )

    # Get datetime obj for validation
    dt_ck = datetime.date(int(y), int(m), int(d))

View on GitHub (pinned to f5988cc097)

Solutions

  1. Normalize to MM-DD-YYYY via strftime('%m-%d-%Y') so the day is always valid and correctly positioned.
  2. Validate input with datetime.strptime(s, '%m-%d-%Y') before calling zeller to get a precise, well-known error message.
  3. If accepting multiple formats, parse to a date object first, then format to the one shape zeller accepts.

Example fix

# before
zeller(raw)  # raw = '31-01-2010' style or malformed

# after
from datetime import datetime
d = datetime.strptime(raw, '%d-%m-%Y')  # parse what you actually receive
zeller(d.strftime('%m-%d-%Y'))
Defensive patterns

Strategy: validation

Validate before calling

from datetime import datetime

def valid_mmddyyyy(s: str) -> bool:
    try:
        datetime.strptime(s, '%m-%d-%Y')
        return True
    except ValueError:
        return False

Try / catch

try:
    day = zeller(s)
except ValueError as e:
    # covers day range plus datetime's own calendar check (e.g. 02-31)
    return f'invalid date {s!r}: {e}'

Prevention

When it happens

Trigger: 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.

Common situations: Day/month transposition; unpadded single-digit days shifting positions ('1-3-2010'); user typos or scraped text with malformed dates.

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/92ef4e6c27f37154. Report an issue: GitHub.