|
|
@@ -2027,27 +2027,30 @@ static APKNode *AddAPKDirs(char *path, APKNode *parent)
|
|
|
|
|
|
static SDL_Time ZipDosTimeToSDLTime(Uint32 dostime)
|
|
|
{
|
|
|
- Uint32 dosdate;
|
|
|
- struct tm unixtime;
|
|
|
- SDL_zero(unixtime);
|
|
|
-
|
|
|
- dosdate = (Uint32) ((dostime >> 16) & 0xFFFF);
|
|
|
- dostime &= 0xFFFF;
|
|
|
-
|
|
|
- /* dissect date */
|
|
|
- unixtime.tm_year = ((dosdate >> 9) & 0x7F) + 80;
|
|
|
- unixtime.tm_mon = ((dosdate >> 5) & 0x0F) - 1;
|
|
|
- unixtime.tm_mday = ((dosdate ) & 0x1F);
|
|
|
-
|
|
|
- /* dissect time */
|
|
|
- unixtime.tm_hour = ((dostime >> 11) & 0x1F);
|
|
|
- unixtime.tm_min = ((dostime >> 5) & 0x3F);
|
|
|
- unixtime.tm_sec = ((dostime << 1) & 0x3E);
|
|
|
-
|
|
|
- /* let mktime calculate daylight savings time. */
|
|
|
- unixtime.tm_isdst = -1;
|
|
|
-
|
|
|
- return ((SDL_Time) mktime(&unixtime));
|
|
|
+ // Note that DOS-style datetimes in a zip don't have timezone info, etc,
|
|
|
+ // so these are treated as UTC for lack of a better option. Also, they have
|
|
|
+ // 2-second precision and the year bits are going to roll over in 2108.
|
|
|
+ // There are possibly better timestamps in extended fields (!!! FIXME: add
|
|
|
+ // support for those), but this field is guaranteed to exist with all its
|
|
|
+ // flaws and is probably Good Enough anyhow.
|
|
|
+ const Uint32 dosdate = (Uint32) ((dostime >> 16) & 0xFFFF);
|
|
|
+ const Uint32 dostime16 = dostime & 0xFFFF;
|
|
|
+
|
|
|
+ const int m = (int) ((dosdate >> 5) & 0x0F);
|
|
|
+ const int d = (int) ((dosdate >> 0) & 0x1F) + 1;
|
|
|
+ const int y = (int) (((dosdate >> 9) & 0x7F) + 1980) - (m <= 2 ? 1 : 0);
|
|
|
+ const int hour = (int) ((dostime16 >> 11) & 0x1F);
|
|
|
+ const int minute = (int) ((dostime16 >> 5) & 0x3F);
|
|
|
+ const int sec = (int) ((dostime16 << 1) & 0x3E);
|
|
|
+
|
|
|
+ // days since 1/1/1970: https://howardhinnant.github.io/date_algorithms.html#days_from_civil
|
|
|
+ const int era = ((y >= 0) ? y : (y - 399)) / 400;
|
|
|
+ const unsigned int yoe = (unsigned int) (y - era * 400); // [0, 399]
|
|
|
+ const unsigned int doy = (((153 * ((m > 2) ? (m - 3) : (m + 9))) + 2) / 5) + (d - 1); // [0, 365]
|
|
|
+ const unsigned int doe = (yoe * 365) + (yoe / 4) - (yoe / 100) + doy; // [0, 146096]
|
|
|
+ const int days = (era * 146097) + ((int) doe) - 719468;
|
|
|
+ const int seconds = (hour * (60 * 60)) + (minute * 60) + (sec);
|
|
|
+ return (SDL_Time) (((Sint64) days) * 86400) + seconds;
|
|
|
}
|
|
|
|
|
|
|