https://github.com/python/cpython/commit/b8d3fddba6e96e693ced0d3b8f6ddbd61428fd32
commit: b8d3fddba6e96e693ced0d3b8f6ddbd61428fd32
branch: main
author: Gregory P. Smith <[email protected]>
committer: gpshead <[email protected]>
date: 2025-12-20T22:47:40-08:00
summary:
gh-70647: Better promote how to safely parse yearless dates in datetime.
(GH-116179)
* gh-70647: Better promote how to safely parse yearless dates in datetime.
Every four years people encounter this because it just isn't obvious.
This moves the footnote up to a note with a code example.
We'd love to change the default year value for datetime but doing
that could have other consequences for existing code. This documented
workaround *always* works.
* doctest code within note is bad, dedent.
* Update to match the error message.
* remove no longer referenced footnote
* ignore the warning in the doctest
* use Petr's suggestion for the docs to hide the warning processing
* cover date.strptime (3.14) as well
files:
M Doc/library/datetime.rst
diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst
index 8ae1c1fb9e46bb..48e7080da6c525 100644
--- a/Doc/library/datetime.rst
+++ b/Doc/library/datetime.rst
@@ -2651,9 +2651,42 @@ Broadly speaking, ``d.strftime(fmt)`` acts like the
:mod:`time` module's
``time.strftime(fmt, d.timetuple())`` although not all objects support a
:meth:`~date.timetuple` method.
-For the :meth:`.datetime.strptime` class method, the default value is
-``1900-01-01T00:00:00.000``: any components not specified in the format string
-will be pulled from the default value. [#]_
+For the :meth:`.datetime.strptime` and :meth:`.date.strptime` class methods,
+the default value is ``1900-01-01T00:00:00.000``: any components not specified
+in the format string will be pulled from the default value.
+
+.. note::
+ When used to parse partial dates lacking a year, :meth:`.datetime.strptime`
+ and :meth:`.date.strptime` will raise when encountering February 29 because
+ the default year of 1900 is *not* a leap year. Always add a default leap
+ year to partial date strings before parsing.
+
+
+.. testsetup::
+
+ # doctest seems to turn the warning into an error which makes it
+ # show up and require matching and prevents the actual interesting
+ # exception from being raised.
+ # Manually apply the catch_warnings context manager
+ import warnings
+ catch_warnings = warnings.catch_warnings()
+ catch_warnings.__enter__()
+ warnings.simplefilter("ignore")
+
+.. testcleanup::
+
+ catch_warnings.__exit__()
+
+.. doctest::
+
+ >>> from datetime import datetime
+ >>> value = "2/29"
+ >>> datetime.strptime(value, "%m/%d")
+ Traceback (most recent call last):
+ ...
+ ValueError: day 29 must be in range 1..28 for month 2 in year 1900
+ >>> datetime.strptime(f"1904 {value}", "%Y %m/%d")
+ datetime.datetime(1904, 2, 29, 0, 0)
Using ``datetime.strptime(date_string, format)`` is equivalent to::
@@ -2790,7 +2823,7 @@ Notes:
include a year in the format. If the value you need to parse lacks a year,
append an explicit dummy leap year. Otherwise your code will raise an
exception when it encounters leap day because the default year used by the
- parser is not a leap year. Users run into this bug every four years...
+ parser (1900) is not a leap year. Users run into that bug every leap year.
.. doctest::
@@ -2817,5 +2850,3 @@ Notes:
.. [#] See R. H. van Gent's `guide to the mathematics of the ISO 8601 calendar
<https://web.archive.org/web/20220531051136/https://webspace.science.uu.nl/~gent0113/calendar/isocalendar.htm>`_
for a good explanation.
-
-.. [#] Passing ``datetime.strptime('Feb 29', '%b %d')`` will fail since 1900
is not a leap year.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]