From 7bf79acacd2e3201813de3946a67fa3ccc0880d8 Mon Sep 17 00:00:00 2001 From: priyanshu2282-cyber Date: Thu, 15 Jan 2026 18:14:11 +0530 Subject: [PATCH 1/3] Preserve UTC semantics for ZIP timestamps --- Lib/zipimport.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/zipimport.py b/Lib/zipimport.py index 19279d1c2bea36..fcabb2746edb88 100644 --- a/Lib/zipimport.py +++ b/Lib/zipimport.py @@ -17,6 +17,7 @@ import _io # for open import marshal # for loads import time # for mktime +import calendar __all__ = ['ZipImportError', 'zipimporter'] @@ -749,7 +750,7 @@ def _compile_source(pathname, source, module): # Convert the date/time values found in the Zip archive to a value # that's compatible with the time stamp stored in .pyc files. def _parse_dostime(d, t): - return time.mktime(( + return calendar.timegm(( (d >> 9) + 1980, # bits 9..15: year (d >> 5) & 0xF, # bits 5..8: month d & 0x1F, # bits 0..4: day From 40adb9056beb6311fb8a27e61a90eea9ad249be8 Mon Sep 17 00:00:00 2001 From: priyanshu2282-cyber Date: Thu, 15 Jan 2026 19:21:11 +0530 Subject: [PATCH 2/3] gh-141431: Treat zipimport DOS timestamps as UTC --- Lib/zipimport.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/Lib/zipimport.py b/Lib/zipimport.py index fcabb2746edb88..6b683d0be6a2bd 100644 --- a/Lib/zipimport.py +++ b/Lib/zipimport.py @@ -17,7 +17,6 @@ import _io # for open import marshal # for loads import time # for mktime -import calendar __all__ = ['ZipImportError', 'zipimporter'] @@ -750,15 +749,27 @@ def _compile_source(pathname, source, module): # Convert the date/time values found in the Zip archive to a value # that's compatible with the time stamp stored in .pyc files. def _parse_dostime(d, t): - return calendar.timegm(( - (d >> 9) + 1980, # bits 9..15: year - (d >> 5) & 0xF, # bits 5..8: month - d & 0x1F, # bits 0..4: day - t >> 11, # bits 11..15: hours - (t >> 5) & 0x3F, # bits 8..10: minutes - (t & 0x1F) * 2, # bits 0..7: seconds / 2 - -1, -1, -1)) - + year=((d >> 9) & 0x7F)+ 1980, # bits 9..15: year + month=(d >> 5) & 0xF, # bits 5..8: month + day=d & 0x1F, # bits 0..4: day + hour=(t >> 11) & 0x1F, # bits 11..15: hours + minute=(t >> 5) & 0x3F, # bits 8..10: minutes + second=(t & 0x1F) * 2 # bits 0..7: seconds / 2 + if month <= 2: + year -= 1 + month += 12 + + days = ( + 365 * year + + year // 4 + - year // 100 + + year // 400 + + (153 * (month - 3) + 2) // 5 + + day + - 719469 + ) + + return days * 86400 + hour * 3600 + minute * 60 + second # Given a path to a .pyc file in the archive, return the # modification time of the matching .py file and its size, # or (0, 0) if no source is available. From 4830eb2787adc4ddbda1f01df8ef55c17bcc7dbf Mon Sep 17 00:00:00 2001 From: priyanshu2282-cyber Date: Thu, 15 Jan 2026 19:39:32 +0530 Subject: [PATCH 3/3] py to pyc fixup --- Lib/test/test_zipimport.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py index dce3e1d9d38e7a..7b25b85cdd0a14 100644 --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -307,7 +307,7 @@ def test2038MTime(self): twenty_thirty_eight_pyc = make_pyc(test_co, 2**32 - 1, len(test_src)) files = {TESTMOD + ".py": test_src, TESTMOD + pyc_ext: twenty_thirty_eight_pyc} - self.doTest(".py", files, TESTMOD) + self.doTest(".pyc", files, TESTMOD) def testPackage(self): packdir = TESTPACK + os.sep