https://github.com/python/cpython/commit/bfb01d8a0c4283553463d87da07e4ff816e69260
commit: bfb01d8a0c4283553463d87da07e4ff816e69260
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: StanFromIreland <[email protected]>
date: 2026-06-27T15:36:31Z
summary:

[3.15] gh-152305: Fix `_pydatetime.time.strftime()` raising on year directives 
(GH-152306) (#152425)

(cherry picked from commit 5733361fdd85519c931e67fd7cab0ff3a11b8ec0)

Co-authored-by: tonghuaroot (童话) <[email protected]>
Co-authored-by: Stan Ulbrych <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-06-26-15-41-34.gh-issue-152305.WnbbBc.rst
M Lib/_pydatetime.py
M Lib/test/datetimetester.py

diff --git a/Lib/_pydatetime.py b/Lib/_pydatetime.py
index db4ea8d30c7064..c47f4e671b39de 100644
--- a/Lib/_pydatetime.py
+++ b/Lib/_pydatetime.py
@@ -272,12 +272,12 @@ def _wrap_strftime(object, format, timetuple):
                     newformat.append(Zreplace)
                 # Note that datetime(1000, 1, 1).strftime('%G') == '1000' so
                 # year 1000 for %G can go on the fast path.
-                elif ((ch in 'YG' or ch in 'FC') and
-                        object.year < 1000 and _need_normalize_century()):
+                elif (ch in 'YGFC' and timetuple[0] < 1000 and
+                        _need_normalize_century()):
                     if ch == 'G':
                         year = int(_time.strftime("%G", timetuple))
                     else:
-                        year = object.year
+                        year = timetuple[0]
                     if ch == 'C':
                         push('{:02}'.format(year // 100))
                     else:
diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py
index 28c3ab2605c45d..192b22ff754003 100644
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -4119,6 +4119,11 @@ def test_strftime_special(self):
         self.assertEqual(t.strftime('\0'*1000), '\0'*1000)
         self.assertEqual(t.strftime('\0%I%p%Z\0%X'), f'\0{s1}\0{s2}')
         self.assertEqual(t.strftime('%I%p%Z\0%X\0'), f'{s1}\0{s2}\0')
+        # gh-152305: the year directives must not raise on a time.
+        for directive, expected in (('%Y', '1900'), ('%G', '1900'),
+                                    ('%C', '19'), ('%F', '1900-01-01')):
+            with self.subTest(directive=directive):
+                self.assertEqual(t.strftime(directive), expected)
 
     def test_format(self):
         t = self.theclass(1, 2, 3, 4)
diff --git 
a/Misc/NEWS.d/next/Library/2026-06-26-15-41-34.gh-issue-152305.WnbbBc.rst 
b/Misc/NEWS.d/next/Library/2026-06-26-15-41-34.gh-issue-152305.WnbbBc.rst
new file mode 100644
index 00000000000000..4f27e2ed016d69
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-06-26-15-41-34.gh-issue-152305.WnbbBc.rst
@@ -0,0 +1,2 @@
+Fix the pure-Python :meth:`datetime.time.strftime` implementation raising 
:exc:`AttributeError` for the
+year directives. Patch by tonghuaroot.

_______________________________________________
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]

Reply via email to