From: Jason Yalim, PhD <4813268+jyalim@users.noreply.github.com> Date: Mon, 9 Feb 2026 12:24:15 +0000 (-0700) Subject: gh-140715: Add `%F` format code support to `strptime()` (GH-140647) X-Git-Tag: v3.15.0a6~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d99f3fc474f34db4176ac67611efec18bde66c7e;p=thirdparty%2FPython%2Fcpython.git gh-140715: Add `%F` format code support to `strptime()` (GH-140647) Also: add tests for the `%T` format code Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> --- diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 3ab3450032ab..7c172471b195 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -2540,7 +2540,7 @@ requires, and these work on all supported platforms. | ``%e`` | The day of the month as a | ␣1, ␣2, ..., 31 | | | | space-padded decimal number. | | | +-----------+--------------------------------+------------------------+-------+ -| ``%F`` | Equivalent to ``%Y-%m-%d``, | 2025-10-11, | \(0) | +| ``%F`` | Equivalent to ``%Y-%m-%d``, | 2025-10-11, | | | | the ISO 8601 format. | 1001-12-30 | | +-----------+--------------------------------+------------------------+-------+ | ``%g`` | Last 2 digits of ISO 8601 year | 00, 01, ..., 99 | \(0) | @@ -2673,10 +2673,10 @@ differences between platforms in handling of unsupported format specifiers. ``%G``, ``%u`` and ``%V`` were added. .. versionadded:: 3.12 - ``%:z`` was added for :meth:`~.datetime.strftime` + ``%:z`` was added for :meth:`~.datetime.strftime`. .. versionadded:: 3.15 - ``%:z`` was added for :meth:`~.datetime.strptime` + ``%:z`` and ``%F`` were added for :meth:`~.datetime.strptime`. Technical Detail ^^^^^^^^^^^^^^^^ diff --git a/Lib/_strptime.py b/Lib/_strptime.py index d011ddf8b181..8b62ea734b7d 100644 --- a/Lib/_strptime.py +++ b/Lib/_strptime.py @@ -418,6 +418,7 @@ class TimeRE(dict): mapping['W'] = mapping['U'].replace('U', 'W') base.__init__(mapping) + base.__setitem__('F', self.pattern('%Y-%m-%d')) base.__setitem__('T', self.pattern('%H:%M:%S')) base.__setitem__('R', self.pattern('%H:%M')) base.__setitem__('r', self.pattern(self.locale_time.LC_time_ampm)) diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 8d39299b3ff4..3784909ee778 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -2193,6 +2193,13 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase): with self.assertRaises(TypeError): self.theclass.fromisocalendar(*isocal) + def test_strptime_F_format(self): + test_date = "2025-10-26" + self.assertEqual( + self.theclass.strptime(test_date, "%F"), + self.theclass.strptime(test_date, "%Y-%m-%d") + ) + ############################################################################# # datetime tests @@ -3780,6 +3787,13 @@ class TestDateTime(TestDate): td = SubclassDatetime(2010, 10, 2, second=3) self.assertEqual(repr(td), "SubclassDatetime(2010, 10, 2, 0, 0, 3)") + def test_strptime_T_format(self): + test_time = "15:00:00" + self.assertEqual( + self.theclass.strptime(test_time, "%T"), + self.theclass.strptime(test_time, "%H:%M:%S") + ) + class TestSubclassDateTime(TestDateTime): theclass = SubclassDatetime diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index 40e114aada67..0784ea6a4cf5 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -649,6 +649,20 @@ class StrptimeTests(unittest.TestCase): time.strptime("Feb 29", "%b %d"), time.strptime("Mar 1", "%b %d")) + def test_strptime_F_format(self): + test_date = "2025-10-26" + self.assertEqual( + time.strptime(test_date, "%F"), + time.strptime(test_date, "%Y-%m-%d") + ) + + def test_strptime_T_format(self): + test_time = "15:00:00" + self.assertEqual( + time.strptime(test_time, "%T"), + time.strptime(test_time, "%H:%M:%S") + ) + class Strptime12AMPMTests(unittest.TestCase): """Test a _strptime regression in '%I %p' at 12 noon (12 PM)""" diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index c360f4a64c26..da0cf494bfa8 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -358,8 +358,8 @@ class TimeTestCase(unittest.TestCase): # Should be able to go round-trip from strftime to strptime without # raising an exception. tt = time.gmtime(self.t) - for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'H', 'I', - 'j', 'm', 'M', 'p', 'S', + for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'F', 'H', 'I', + 'j', 'm', 'M', 'p', 'S', 'T', 'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'): format = '%' + directive if directive == 'd': diff --git a/Misc/NEWS.d/next/Library/2025-10-27-00-13-04.gh-issue-140715.WkozE0.rst b/Misc/NEWS.d/next/Library/2025-10-27-00-13-04.gh-issue-140715.WkozE0.rst new file mode 100644 index 000000000000..c2bb69b894c1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-10-27-00-13-04.gh-issue-140715.WkozE0.rst @@ -0,0 +1 @@ +Add ``'%F'`` support to :meth:`~datetime.datetime.strptime`.