diff --git a/Lib/test/test_zoneinfo/test_zoneinfo.py b/Lib/test/test_zoneinfo/test_zoneinfo.py index 9483c2fc512e0d..21033882e148a3 100644 --- a/Lib/test/test_zoneinfo/test_zoneinfo.py +++ b/Lib/test/test_zoneinfo/test_zoneinfo.py @@ -1184,6 +1184,11 @@ def test_invalid_tzstr(self): # Invalid weekday "AAA4BBB,M1.1.7/2,M2.1.1/2", "AAA4BBB,M1.1.1/2,M2.1.7/2", + # Invalid Mm.w.d separator + "AAA4BBB,M3.2X0,M11.1.0", + "AAA4BBB,M3.2.0,M11.1X0", + "AAA4BBB,M3.2-0,M11.1.0/3", + "AAA4BBB,M3.2.0/2,M11.1:0", # Invalid numeric offset "AAA4BBB,-1/2,20/2", "AAA4BBB,1/2,-1/2", diff --git a/Lib/zoneinfo/_zoneinfo.py b/Lib/zoneinfo/_zoneinfo.py index 7063eb6a9025ac..3903d57d55417e 100644 --- a/Lib/zoneinfo/_zoneinfo.py +++ b/Lib/zoneinfo/_zoneinfo.py @@ -707,7 +707,7 @@ def _parse_dst_start_end(dststr): type = date[:1] if type == "M": n_is_julian = False - m = re.fullmatch(r"M(\d{1,2})\.(\d).(\d)", date, re.ASCII) + m = re.fullmatch(r"M(\d{1,2})\.(\d)\.(\d)", date, re.ASCII) if m is None: raise ValueError(f"Invalid dst start/end date: {dststr}") date_offset = tuple(map(int, m.groups())) diff --git a/Misc/NEWS.d/next/Library/2026-06-26-12-50-26.gh-issue-152246.MfXMd1.rst b/Misc/NEWS.d/next/Library/2026-06-26-12-50-26.gh-issue-152246.MfXMd1.rst new file mode 100644 index 00000000000000..0858199a9fa279 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-26-12-50-26.gh-issue-152246.MfXMd1.rst @@ -0,0 +1,2 @@ +Fix the pure-Python :mod:`zoneinfo` parser accepting an invalid POSIX TZ +transition rule with a non-period separator. Patch by tonghuaroot.