From fb1f18c0da6af4e15d5f6ed531b637810205232a Mon Sep 17 00:00:00 2001 From: yuanx749 Date: Sat, 23 May 2026 13:31:29 +0300 Subject: [PATCH 1/4] Add test --- Lib/test/test_imaplib.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py index fb256fb7cbcd344..8660bb058b99676 100644 --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -67,6 +67,15 @@ def test_Time2Internaldate(self): internal = imaplib.Time2Internaldate(t) self.assertEqual(internal, expected) + @run_with_tz('STD-1DST,M3.2.0,M11.1.0') + def test_Time2Internaldate_datetime_timetuple(self): + date_time = datetime.fromtimestamp(2000000000).timetuple() + self.assertIsNone(date_time.tm_gmtoff) + self.assertEqual( + imaplib.Time2Internaldate(date_time), + '"18-May-2033 05:33:20 +0200"', + ) + def test_that_Time2Internaldate_returns_a_result(self): # Without tzset, we can check only that it successfully # produces a result, not the correctness of the result itself, From 97f1381c8f50acae8bd62d70303475025d5c1a16 Mon Sep 17 00:00:00 2001 From: yuanx749 Date: Sat, 23 May 2026 13:32:06 +0300 Subject: [PATCH 2/4] Handle struct_time with no gmtoff in imaplib --- Lib/imaplib.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/imaplib.py b/Lib/imaplib.py index 497b5a60cecb083..fb5ed0ae85b750e 100644 --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -1847,6 +1847,8 @@ def Time2Internaldate(date_time): try: gmtoff = date_time.tm_gmtoff except AttributeError: + gmtoff = None + if gmtoff is None: if time.daylight: dst = date_time[8] if dst == -1: From da04c68179d96098cdd5e2dc2e02d60c8bd517c9 Mon Sep 17 00:00:00 2001 From: yuanx749 Date: Sat, 23 May 2026 13:32:39 +0300 Subject: [PATCH 3/4] Add news entry --- .../next/Library/2026-06-21-15-50-24.gh-issue-86165.dyac1G.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-06-21-15-50-24.gh-issue-86165.dyac1G.rst diff --git a/Misc/NEWS.d/next/Library/2026-06-21-15-50-24.gh-issue-86165.dyac1G.rst b/Misc/NEWS.d/next/Library/2026-06-21-15-50-24.gh-issue-86165.dyac1G.rst new file mode 100644 index 000000000000000..0b630e9ae346834 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-21-15-50-24.gh-issue-86165.dyac1G.rst @@ -0,0 +1,3 @@ +Fix :func:`imaplib.Time2Internaldate` to use the local timezone offset for +``time.struct_time`` values with ``tm_gmtoff`` set to ``None``, as returned by +``datetime.datetime.timetuple()``. Contributed by Xiao Yuan. From 9b4a015f4599723fd9fed738f3154c229caf12fa Mon Sep 17 00:00:00 2001 From: yuanx749 Date: Thu, 2 Jul 2026 16:59:53 +0300 Subject: [PATCH 4/4] Simplify tm_gmtoff lookup --- Lib/imaplib.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Lib/imaplib.py b/Lib/imaplib.py index 29f445b7814ae72..70abfa741444c30 100644 --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -1869,10 +1869,7 @@ def Time2Internaldate(date_time): dt = datetime.fromtimestamp(date_time, timezone.utc).astimezone() elif isinstance(date_time, tuple): - try: - gmtoff = date_time.tm_gmtoff - except AttributeError: - gmtoff = None + gmtoff = getattr(date_time, "tm_gmtoff", None) if gmtoff is None: if time.daylight: dst = date_time[8]