ValueError: time data does not match format (strptime, tested)
ValueError: time data '...' does not match format '...' and its sibling unconverted data remains come from datetime.strptime(). We ran 30 real-world string/format pairs on Python 3.13.5 and found that the errors are the easy part: two common formats parse without error and give the wrong answer.
1. Two different messages, two different problems
from datetime import datetime
for s, fmt in [("2024-01-05", "%d/%m/%Y"),
("2024-01-05\n", "%Y-%m-%d"),
("2024-01-05 14:30:00", "%Y-%m-%d")]:
try:
datetime.strptime(s, fmt)
except ValueError as e:
print(repr(e))
ValueError("time data '2024-01-05' does not match format '%d/%m/%Y'")
ValueError('unconverted data remains: \n')
ValueError('unconverted data remains: 14:30:00')
Measured: time data ... does not match format means parsing failed somewhere in the middle: here the string uses - and starts with the year, the format expects / and the day first. unconverted data remains: ... means the format matched fine but the string kept going. The text after the colon is the leftover, and it is easy to miss when it is a \n from readline() or a trailing space: the message looks like it ends in nothing. Call .strip() on the input, or add the time part (" %H:%M:%S") to the format.
2. ISO timestamps ending in Z
from datetime import datetime
s = "2024-01-05T14:30:00Z"
print(repr(datetime.strptime(s, "%Y-%m-%dT%H:%M:%SZ")))
print(repr(datetime.strptime(s, "%Y-%m-%dT%H:%M:%S%z")))
print(repr(datetime.fromisoformat(s)))
datetime.datetime(2024, 1, 5, 14, 30)
datetime.datetime(2024, 1, 5, 14, 30, tzinfo=datetime.timezone.utc)
datetime.datetime(2024, 1, 5, 14, 30, tzinfo=datetime.timezone.utc)
Measured: putting a literal Z in the format parses without error but returns a naive datetime: the “this is UTC” information is thrown away, and later comparisons with aware datetimes raise TypeError: can't compare offset-naive and offset-aware datetimes. Use %z, which accepts Z and +05:30 and returns timezone.utc, or skip the format entirely: datetime.fromisoformat() accepts the trailing Z on Python 3.11 and newer (we tested 3.13.5). If the string has fractional seconds (.123Z), the strptime format needs .%f as well or you get the “does not match” error; fromisoformat handles both.
3. 12-hour times: the silent wrong answer
from datetime import datetime
s = "Jan 5 2024 2:30 PM"
print(datetime.strptime(s, "%b %d %Y %H:%M %p"))
print(datetime.strptime(s, "%b %d %Y %I:%M %p"))
2024-01-05 02:30:00
2024-01-05 14:30:00
Measured: with %H (24-hour), the PM is matched by %p and then ignored. 2:30 PM becomes 02:30 with no error at all. %p only has an effect together with %I (12-hour clock). This one never raises, so grep your formats for %H next to %p.
4. %Z only knows a few names
from datetime import datetime
for s in ["2024-01-05 14:30:00 UTC", "2024-01-05 14:30:00 EST"]:
try:
print(repr(datetime.strptime(s, "%Y-%m-%d %H:%M:%S %Z")))
except ValueError as e:
print(repr(e))
datetime.datetime(2024, 1, 5, 14, 30)
ValueError("time data '2024-01-05 14:30:00 EST' does not match format '%Y-%m-%d %H:%M:%S %Z'")
Measured: %Z accepted UTC (and GMT, which we also tested) but the result is naive: the zone is checked, then discarded. EST was rejected outright. Per the docs, %Z only accepts UTC, GMT and the machine's local time.tzname names, so the same code can pass on one server and fail on another. Prefer numeric offsets with %z; if your input really has names like EST, map them to offsets yourself or use zoneinfo.
5. Errors that look like the same problem but aren't
from datetime import datetime
for s, fmt in [("2/30/2024", "%m/%d/%Y"),
("January 5 2024", "%b %d %Y"),
("1704465000", "%s")]:
try:
datetime.strptime(s, fmt)
except ValueError as e:
print(repr(e))
ValueError('day is out of range for month')
ValueError("time data 'January 5 2024' does not match format '%b %d %Y'")
ValueError("'s' is a bad directive in format '%s'")
Measured: February 30 matches the format and then fails validation with day is out of range for month — the format is right, the data is wrong. %b is the abbreviated month (Jan) and won't accept January; use %B for full names (both are locale-dependent). %s (Unix timestamp) is not a strptime directive; use datetime.fromtimestamp(int(s), tz=timezone.utc). Also note that %d and %m accept unpadded values (5/1/2024 parsed fine), and %Y requires four digits (24-01-05 failed; use %y for two).
6. A parser for messy input
from datetime import datetime
FORMATS = ["%Y-%m-%d", "%d/%m/%Y", "%b %d %Y", "%B %d %Y"]
def parse_date(s):
s = s.strip()
try:
return datetime.fromisoformat(s)
except ValueError:
pass
for fmt in FORMATS:
try:
return datetime.strptime(s, fmt)
except ValueError:
continue
raise ValueError(f"unrecognised date {s!r}; tried ISO 8601 and {FORMATS}")
for s in ["2024-01-05\n", "05/01/2024", "January 5 2024", "2024-01-05T14:30:00Z"]:
print(repr(parse_date(s)))
try:
parse_date("5th Jan")
except ValueError as e:
print(e)
datetime.datetime(2024, 1, 5, 0, 0)
datetime.datetime(2024, 1, 5, 0, 0)
datetime.datetime(2024, 1, 5, 0, 0)
datetime.datetime(2024, 1, 5, 14, 30, tzinfo=datetime.timezone.utc)
unrecognised date '5th Jan'; tried ISO 8601 and ['%Y-%m-%d', '%d/%m/%Y', '%b %d %Y', '%B %d %Y']
Strip first, try fromisoformat() (which covers most machine-written timestamps), then a short list of known formats, and raise an error that shows the actual value. Keep the list short and ordered on purpose: 05/01/2024 is 5 January with %d/%m/%Y first and 1 May if %m/%d/%Y comes first, and both “succeed”. Don't put both in the same list; decide per data source.
Frequently asked questions
What does 'time data does not match format' mean?
strptime() hit a character in the string that the format didn't expect, for example '-' where the format has '/', or a 2-digit year where %Y needs 4. We measured that the message shows the whole string and format but not the position where they diverged.
What does 'unconverted data remains' mean?
The format matched the start of the string but there was text left over. We measured it on a trailing newline from readline() (the message then looks empty) and on a time part the format didn't include. Strip the input or extend the format.
How do I parse an ISO 8601 string ending in Z?
Use datetime.fromisoformat(s) on Python 3.11+, or the %z directive in strptime. We measured that both return tzinfo=timezone.utc, while a literal 'Z' in the format returns a naive datetime that has lost the UTC information.
Why is my PM time parsed as AM?
%p only works with %I. With %H we measured that 'Jan 5 2024 2:30 PM' parses to 02:30 with no error; with %I it parses to 14:30.
Why does %Z fail on EST?
strptime's %Z only accepts UTC, GMT and the local machine's time zone names. We measured 'UTC' parsing (but returning a naive datetime) and 'EST' raising does not match format.
Written with AI assistance. Measured on 2026-10-09 with Python 3.13.5's datetime.strptime() and datetime.fromisoformat() on 30 input/format pairs: separator and year mismatches, trailing newline, ISO 8601 with Z and fractional seconds, %H vs %I with %p, %Z with UTC/GMT/EST, out-of-range days, %b vs %B and %s. Every code block on this page was run verbatim and its output pasted from that run. PlainHeaders is our extension; Python's datetime module is built in.