When strptime parses a string, any components not specified in the format are filled in using default values. A format without a year produces a date in 1900, which is rarely what the caller intended and is not stated anywhere in the code. This choice also has a practical consequence: because 1900 is not a leap year, 29 February cannot be parsed when the year is omitted.
For example, a format that specifies a day of month but no year:
from datetime import datetime
print(datetime.strptime('15', '%d'))
print(datetime.strptime('02/15', '%m/%d'))
On Python 3.14 still produces a result, but with deprecation:
intro.py:3: DeprecationWarning: Parsing dates involving a day of month without a year specified is ambiguous
1900-01-15 00:00:00
intro.py:4: DeprecationWarning: Parsing dates involving a day of month without a year specified is ambiguous
1900-02-15 00:00:00
Both calls succeed, and both return a date in a year that was never supplied.
Since Python 3.15, the call is now rejected instead of silently assuming a year. Note that the restriction applies to the day of month only. A format such as %m continues to work on its own, since a month without a year is unambiguous, unlike a day of the month.
ValueError: Day of month directive '%d' may not be used without a year directive
The fix is to include a year directive in both the input and the format:
from datetime import datetime
print(datetime.strptime('15/2026', '%d/%Y')) # 2026-01-15 00:00:00
print(datetime.strptime('02/15/2026', '%m/%d/%Y')) # 2026-02-15 00:00:00
Leave a Comment
Cancel reply