← Back

Home › Errors › ValueError

ValueError: time data does not match format

Exception: ValueErrorCategory: runtime (datetime parsing)Raised at: the strptime() or datetime.strptime() call whose format string disagrees with the input

What this error means

strptime parses a string into a datetime using a format string you supply. This error means the string and the format disagree — even by one character.

Traceback (most recent call last):
  File "demo.py", line 3, in <module>
    dt = datetime.strptime("2026-10-11", "%d/%m/%Y")
ValueError: time data '2026-10-11' does not match format '%d/%m/%Y'

The message quotes both sides, which makes it directly diagnosable: line them up character by character and the mismatch is usually obvious within a few seconds.

from datetime import datetime

datetime.strptime("2026-10-11", "%Y-%m-%d")     # ✅
datetime.strptime("2026-10-11", "%d/%m/%Y")     # 💥 separators differ
datetime.strptime("11/10/2026", "%d/%m/%Y")     # ✅
datetime.strptime("2026-10-11", "%Y-%m-%d")     # ✅ exact match required

The directives you need

%Y   four-digit year      2026          %y   two-digit year    26
%m   month, zero-padded   01-12         %-m  no padding (Unix)  1-12
%d   day, zero-padded     01-31         %-d  no padding (Unix)
%H   hour, 24-hour        00-23         %I   hour, 12-hour     01-12
%M   minute               00-59         %S   second            00-59
%f   microseconds         000000-999999
%p   AM / PM
%z   UTC offset           +0530         %Z   timezone name     IST
%j   day of year          001-366
%a   abbreviated weekday  Mon           %A   full weekday      Monday
%b   abbreviated month    Oct           %B   full month        October

Two details cause a disproportionate share of failures. %Y is four digits and %y is two — using %y on 2026 fails. And zero-padding matters on some platforms: 1/10/2026 may fail against %d/%m/%Y on Windows, where %-d is not supported at all.

The mismatches that actually happen

s = "2026-10-11 14:30:00"

# 1 — wrong separators
strptime(s, "%Y/%m/%d %H:%M:%S")       # 💥 dashes vs slashes

# 2 — missing a component
strptime(s, "%Y-%m-%d")                # 💥 the time part is unaccounted for

# 3 — extra characters in the input
strptime("2026-10-11T14:30:00Z", "%Y-%m-%d %H:%M:%S")   # 💥 the T and Z

# 4 — 12-hour clock without %p
strptime("2026-10-11 02:30 PM", "%Y-%m-%d %I:%M")       # 💥 PM unaccounted for
strptime("2026-10-11 02:30 PM", "%Y-%m-%d %I:%M %p")    # ✅

# 5 — hour out of range for the clock
strptime("2026-10-11 14:30", "%Y-%m-%d %I:%M")          # 💥 %I maxes at 12
strptime("2026-10-11 14:30", "%Y-%m-%d %H:%M")          # ✅

# 6 — month name in a different locale
strptime("11 अक्टूबर 2026", "%d %B %Y")                   # 💥 %B expects English

Cause 2 deserves emphasis: strptime requires the format to account for the entire string. Leftover characters are an error, not something it skips. That is why ISO timestamps with a trailing Z fail so reliably.

ISO 8601: use fromisoformat

If the input is ISO 8601 — and most API responses, database exports and log lines are — do not build a format string at all:

from datetime import datetime

# Python 3.11+ handles the full ISO 8601 set, including Z
datetime.fromisoformat("2026-10-11T14:30:00")
datetime.fromisoformat("2026-10-11T14:30:00+05:30")
datetime.fromisoformat("2026-10-11T14:30:00Z")       # ✅ on 3.11+

# On Python 3.7 to 3.10, Z is not accepted — strip it first
raw = "2026-10-11T14:30:00Z"
datetime.fromisoformat(raw.replace("Z", "+00:00"))

# date-only
datetime.fromisoformat("2026-10-11")

This removes an entire class of bug. fromisoformat is stricter and more predictable than any hand-written format string, and it handles the timezone suffix correctly, which hand-rolled %z handling often does not.

Parsing many formats

When input comes from users or from several systems, try a list of formats rather than guessing one:

from datetime import datetime

FORMATS = [
    "%Y-%m-%dT%H:%M:%S%z",
    "%Y-%m-%dT%H:%M:%S",
    "%Y-%m-%d %H:%M:%S",
    "%Y-%m-%d",
    "%d/%m/%Y",
    "%d-%m-%Y",
]

def parse_when(raw):
    '''Return a datetime for any accepted layout, or None.'''
    text = str(raw).strip().replace("Z", "+00:00")
    for fmt in FORMATS:
        try:
            return datetime.strptime(text, fmt)
        except ValueError:
            continue
    return None

for probe in ["2026-10-11", "11/10/2026", "2026-10-11T14:30:00Z", "nonsense"]:
    print(probe, "->", parse_when(probe))

Returning None and letting the caller decide is usually better than raising, when the source is external data you cannot control. But log what failed — a parser that silently drops rows hides a data problem until much later.

Timezones

A datetime without timezone information is *naive*, and comparing a naive datetime with an aware one raises TypeError — a different error that arrives later and is harder to trace:

from datetime import datetime, timezone

naive = datetime(2026, 10, 11, 14, 30)
aware = datetime(2026, 10, 11, 14, 30, tzinfo=timezone.utc)

naive < aware        # 💥 TypeError: can't compare offset-naive and
                     #    offset-aware datetimes

# make the naive one aware, stating the assumption explicitly
naive_ist = naive.replace(tzinfo=timezone(timedelta(hours=5, minutes=30)))

# convert between zones
aware.astimezone(timezone.utc)

# current time — prefer the aware form
datetime.now(timezone.utc)     # ✅ aware
datetime.utcnow()              # ⚠️ deprecated in 3.12, returns naive

Decide once, at the boundary, whether your datetimes are aware or naive, and keep them consistent. Mixing them is the source of most real-world timezone bugs, and the failure usually surfaces far from where the inconsistency was introduced.

Related messages worth knowing

🇮🇳 Hindi में समझें

ValueError: time data does not match format tab aata hai jab strptime() ko diya gaya format string aur actual input aapas me mel nahi khaate — ek character ka farq bhi kaafi hai. Ye message dono taraf quote karta hai, isliye diagnose karna aasaan hai: dono ko character-by-character milaao, mismatch turant dikh jaata hai. Sabse common wajah: galat separators (- ki jagah /), koi component missing (format poori string account nahi karta — strptime ko poori string chahiye, bacha hua hissa error hai), input me extra characters (ISO wala T aur Z), 12-hour clock ke saath %p na lagana, aur %I par 24-hour time dena (%I sirf 12 tak jaata hai, 14 ke liye %H chahiye). Do directives sabse zyada confuse karti hain: %Y chaar digit ka saal hai aur %y do digit ka — 2026 par %y fail hoga. Aur zero-padding platform par depend karti hai; Windows par %-d supported hi nahi hai. Sabse accha fix: agar input ISO 8601 hai (API responses, database exports, logs — zyada tar yahi hota hai) to format string banao hi mat, datetime.fromisoformat() use karo. Python 3.11+ trailing Z bhi sambhaal leta hai; 3.7–3.10 par Z ko +00:00 se replace kar do. Timezone ka ek alag jhagda hai: naive datetime (bina timezone) aur aware datetime ko compare karne par TypeError aata hai — alag error, baad me, aur trace karna mushkil. Isliye boundary par hi tay kar lo ki aapke datetimes aware hain ya naive, aur consistent rakho.

ValueError Hindi में समझें →