14

Is it possible to force a specific timestamp for a file when adding it to a zipfile?

Something along these lines:

with ZipFile('spam.zip', 'w') as myzip:
  myzip.write('eggs.txt', date_time=(1752, 9, 9, 15, 0, 0))

Can I change the ZipInfo on a member of a zipfile?

Dharman
  • 30,962
  • 25
  • 85
  • 135
dantje
  • 1,739
  • 1
  • 13
  • 25

1 Answers1

10

Looking at the source for ZipFile.write() in CPython 3.7, the method always gets its ZipInfo by examining the file on disk—including a bunch of metadata like modified time and OS-specific attributes (see the ZipInfo.from_file() source).

So, to get around this limitation, you'll need to provide your own ZipInfo when writing the file—that means using ZipFile.writestr() and giving it both a ZipInfo and the file data you read from disk, like so:

from zipfile import ZipFile, ZipInfo
with ZipFile('spam.zip', 'w') as myzip, open('eggs.txt') as txt_to_write:
    info = ZipInfo(filename='eggs.txt',
                   # Note that dates prior to 1 January 1980 are not supported
                   date_time=(1980, 1, 1, 0, 0, 0))
    myzip.writestr(info, txt_to_write.read())

Alternatively, if you only want to modify the ZipInfo's date, you could get it from ZipInfo.from_file() and just reset its date_time field:

info = ZipInfo.from_file('eggs.txt')
info.date_time = (1980, 1, 1, 0, 0, 0)

This is better in the general case where you do still want to preserve special OS attributes.

s3cur3
  • 2,749
  • 2
  • 27
  • 42
  • 3
    +1 The problem of having the same hashes for two zip files, where one is created from re-zipping the content of the other, took me 2 hours and I didn't find a solution. Your answer is the solution to my problem. Thanks. – sema Oct 22 '20 at 15:05
  • 1
    @sema That was exactly my use case as well. I needed to be able to create reproducible ZIPs, such that the ZIP archive would be bit-for-bit identical when created from files with the same contents. Glad I could help someone else. :) – s3cur3 Oct 23 '20 at 01:54