]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-136028: Fix parsing month names containing "İ" (U+0130) in strptime() (GH-136029)
authorSerhiy Storchaka <storchaka@gmail.com>
Fri, 27 Jun 2025 13:47:03 +0000 (16:47 +0300)
committerGitHub <noreply@github.com>
Fri, 27 Jun 2025 13:47:03 +0000 (16:47 +0300)
This affects locales az_AZ, ber_DZ, ber_MA and crh_UA.

Lib/_strptime.py
Lib/test/test_strptime.py
Misc/NEWS.d/next/Library/2025-06-27-13-34-28.gh-issue-136028.RY727g.rst [new file with mode: 0644]

index 7ac6f36360cb69be597fe0b3edb2480f7d76023f..cdc55e8daaffa6d3dbdccd445574b5e3ce9911ed 100644 (file)
@@ -42,6 +42,14 @@ def _findall(haystack, needle):
         yield i
         i += len(needle)
 
+def _fixmonths(months):
+    yield from months
+    # The lower case of 'İ' ('\u0130') is 'i\u0307'.
+    # The re module only supports 1-to-1 character matching in
+    # case-insensitive mode.
+    for s in months:
+        if 'i\u0307' in s:
+            yield s.replace('i\u0307', '\u0130')
 
 lzh_TW_alt_digits = (
     # 〇:一:二:三:四:五:六:七:八:九
@@ -366,8 +374,8 @@ class TimeRE(dict):
             'z': r"(?P<z>([+-]\d\d:?[0-5]\d(:?[0-5]\d(\.\d{1,6})?)?)|(?-i:Z))?",
             'A': self.__seqToRE(self.locale_time.f_weekday, 'A'),
             'a': self.__seqToRE(self.locale_time.a_weekday, 'a'),
-            'B': self.__seqToRE(self.locale_time.f_month[1:], 'B'),
-            'b': self.__seqToRE(self.locale_time.a_month[1:], 'b'),
+            'B': self.__seqToRE(_fixmonths(self.locale_time.f_month[1:]), 'B'),
+            'b': self.__seqToRE(_fixmonths(self.locale_time.a_month[1:]), 'b'),
             'p': self.__seqToRE(self.locale_time.am_pm, 'p'),
             'Z': self.__seqToRE((tz for tz_names in self.locale_time.timezone
                                         for tz in tz_names),
index e52c46f8c58ccee90321cb58d5636bbaf976164e..0241e543cd7ddedc6a39f0a7b414defe4f60e625 100644 (file)
@@ -337,6 +337,15 @@ class StrptimeTests(unittest.TestCase):
             self.roundtrip('%B', 1, (1900, m, 1, 0, 0, 0, 0, 1, 0))
             self.roundtrip('%b', 1, (1900, m, 1, 0, 0, 0, 0, 1, 0))
 
+    @run_with_locales('LC_TIME', 'az_AZ', 'ber_DZ', 'ber_MA', 'crh_UA')
+    def test_month_locale2(self):
+        # Test for month directives
+        # Month name contains 'İ' ('\u0130')
+        self.roundtrip('%B', 1, (2025, 6, 1, 0, 0, 0, 6, 152, 0))
+        self.roundtrip('%b', 1, (2025, 6, 1, 0, 0, 0, 6, 152, 0))
+        self.roundtrip('%B', 1, (2025, 7, 1, 0, 0, 0, 1, 182, 0))
+        self.roundtrip('%b', 1, (2025, 7, 1, 0, 0, 0, 1, 182, 0))
+
     def test_day(self):
         # Test for day directives
         self.roundtrip('%d %Y', 2)
diff --git a/Misc/NEWS.d/next/Library/2025-06-27-13-34-28.gh-issue-136028.RY727g.rst b/Misc/NEWS.d/next/Library/2025-06-27-13-34-28.gh-issue-136028.RY727g.rst
new file mode 100644 (file)
index 0000000..9859df7
--- /dev/null
@@ -0,0 +1,3 @@
+Fix parsing month names containing "İ" (U+0130, LATIN CAPITAL LETTER I WITH
+DOT ABOVE) in :func:`time.strptime`. This affects locales az_AZ, ber_DZ,
+ber_MA and crh_UA.