Datas dentro do ZIP
Um ZIP guarda a data de cada arquivo em mais de um campo, cada um com seu fuso e seu limite.
Cada arquivo dentro de um ZIP tem pelo menos uma data, e muitas vezes mais de uma:
| Campo | Onde fica | O que guarda | Limites |
|---|---|---|---|
| DOS date/time | cabeçalho de cada entrada | data e hora locais de quem compactou, sem fuso | segundos de 2 em 2; ano de 1980 a 2107 (7 bits) |
UT (extra field 0x5455) |
campo extra, Info-ZIP | segundos desde 1970 em UTC (o "Unix time") | 32 bits: até 2106-02-07 sem sinal, 2038-01-19 com sinal |
NTFS (extra field 0x000a) |
campo extra, Windows | intervalos de 100 ns desde 1601 em UTC | 64 bits, sem problema prático |
O campo DOS não diz o fuso. Se ele bate com o UT lido em UTC, quem compactou estava em UTC; se difere em 3 horas, estava em UTC-3. As ferramentas mostram coisas diferentes: zipinfo -v mostra os dois campos (e a linha local no fuso do seu computador; use TZ=UTC zipinfo -v), 7z l e unzip -l mostram o UT convertido para o seu fuso, e o zipfile do Python mostra só o DOS:
import zipfile
for i in zipfile.ZipFile("a.zip").infolist():
print(i.filename, i.date_time) # campo DOS, sem fuso
No hexadecimal, o campo UT aparece como 55 54, o tamanho (09 00 ou 05 00), uma flag (03 = há hora de modificação e de acesso) e os segundos em 4 bytes little-endian, ou seja, de trás para a frente. O CyberChef (abre em nova aba) converte o número com From UNIX Timestamp.
Quando os dois campos discordam, a data verdadeira é a que explica os dois: um contador de 32 bits que estourou volta a contar do zero, e somar 2^32 segundos pode reconciliar o UT com o ano do DOS.