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
- ValueError: the parent guide — the whole family of right-type-wrong-value failures.
- ValueError: invalid literal for int() with base 10 — the same shape of failure when converting text to a number.
- TypeError — what you get when comparing a naive datetime with an aware one.
🇮🇳 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.