diff options
author | blhsing <blhsing@gmail.com> | 2024-08-23 15:45:03 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-23 15:45:03 (GMT) |
commit | 126910edba812a01794f307b0cfa2a7f02bda190 (patch) | |
tree | e86e74c3e38f2b8cfcbe9484dc696a0c52767a3f /Lib | |
parent | 7cd3aa42f0cf72bf9a214e2630850879fe078377 (diff) | |
download | cpython-126910edba812a01794f307b0cfa2a7f02bda190.zip cpython-126910edba812a01794f307b0cfa2a7f02bda190.tar.gz cpython-126910edba812a01794f307b0cfa2a7f02bda190.tar.bz2 |
gh-122272: Guarantee specifiers %F and %C for datetime.strftime to be 0-padded (GH-122436)
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/_pydatetime.py | 25 | ||||
-rw-r--r-- | Lib/test/datetimetester.py | 17 |
2 files changed, 34 insertions, 8 deletions
diff --git a/Lib/_pydatetime.py b/Lib/_pydatetime.py index 27cacb8..78432d4 100644 --- a/Lib/_pydatetime.py +++ b/Lib/_pydatetime.py @@ -215,6 +215,17 @@ def _need_normalize_century(): _normalize_century = True return _normalize_century +_supports_c99 = None +def _can_support_c99(): + global _supports_c99 + if _supports_c99 is None: + try: + _supports_c99 = ( + _time.strftime("%F", (1900, 1, 1, 0, 0, 0, 0, 1, 0)) == "1900-01-01") + except ValueError: + _supports_c99 = False + return _supports_c99 + # Correctly substitute for %z and %Z escapes in strftime formats. def _wrap_strftime(object, format, timetuple): # Don't call utcoffset() or tzname() unless actually needed. @@ -272,14 +283,20 @@ def _wrap_strftime(object, format, timetuple): # strftime is going to have at this: escape % Zreplace = s.replace('%', '%%') newformat.append(Zreplace) - elif ch in 'YG' and object.year < 1000 and _need_normalize_century(): - # Note that datetime(1000, 1, 1).strftime('%G') == '1000' so - # year 1000 for %G can go on the fast path. + # 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 _can_support_c99()) and + object.year < 1000 and _need_normalize_century()): if ch == 'G': year = int(_time.strftime("%G", timetuple)) else: year = object.year - push('{:04}'.format(year)) + if ch == 'C': + push('{:02}'.format(year // 100)) + else: + push('{:04}'.format(year)) + if ch == 'F': + push('-{:02}-{:02}'.format(*timetuple[1:3])) else: push('%') push(ch) diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 38de110..0265643 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -1710,13 +1710,22 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase): (1000, 0), (1970, 0), ) - for year, offset in dataset: - for specifier in 'YG': + specifiers = 'YG' + if _time.strftime('%F', (1900, 1, 1, 0, 0, 0, 0, 1, 0)) == '1900-01-01': + specifiers += 'FC' + for year, g_offset in dataset: + for specifier in specifiers: with self.subTest(year=year, specifier=specifier): d = self.theclass(year, 1, 1) if specifier == 'G': - year += offset - self.assertEqual(d.strftime(f"%{specifier}"), f"{year:04d}") + year += g_offset + if specifier == 'C': + expected = f"{year // 100:02d}" + else: + expected = f"{year:04d}" + if specifier == 'F': + expected += f"-01-01" + self.assertEqual(d.strftime(f"%{specifier}"), expected) def test_replace(self): cls = self.theclass |