I think there’s a bug in ZipFile::Builder::Item::writeTimeAndDate in juce_ZipFile.cpp. The seconds value isn’t being divided by 2 before packing into the DOS time format.
The DOS time format stores seconds/2 in a 5-bit field (0-29), but the current code writes t.getSeconds() directly:
target.writeShort ((short) (t.getSeconds() + (t.getMinutes() << 5) + (t.getHours() << 11)));
Should be:
target.writeShort ((short) ((t.getSeconds() >> 1) + (t.getMinutes() << 5) + (t.getHours() << 11)));
Without the >> 1, any seconds value over 31 bleeds into the minutes bits, corrupting both fields. When you read the zip back with parseFileTime, you can end up with seconds of 60 or 62, and the minutes/hours can be wrong too.
The decode side in parseFileTime correctly does (time & 31) << 1, so it’s expecting the halved value — the encode just isn’t providing it.
Easy to reproduce: create a zip with a file whose timestamp has seconds >= 32, then read it back and check the time.
