diff options
Diffstat (limited to 'CPP/Windows/TimeUtils.cpp')
-rw-r--r-- | CPP/Windows/TimeUtils.cpp | 90 |
1 files changed, 76 insertions, 14 deletions
diff --git a/CPP/Windows/TimeUtils.cpp b/CPP/Windows/TimeUtils.cpp index e80ae13..bbd79ba 100644 --- a/CPP/Windows/TimeUtils.cpp +++ b/CPP/Windows/TimeUtils.cpp | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | #ifndef _WIN32 | 5 | #ifndef _WIN32 |
6 | #include <sys/time.h> | 6 | #include <sys/time.h> |
7 | #include <time.h> | ||
7 | #endif | 8 | #endif |
8 | 9 | ||
9 | #include "Defs.h" | 10 | #include "Defs.h" |
@@ -13,13 +14,13 @@ namespace NWindows { | |||
13 | namespace NTime { | 14 | namespace NTime { |
14 | 15 | ||
15 | static const UInt32 kNumTimeQuantumsInSecond = 10000000; | 16 | static const UInt32 kNumTimeQuantumsInSecond = 10000000; |
16 | static const UInt32 kFileTimeStartYear = 1601; | 17 | static const unsigned kFileTimeStartYear = 1601; |
17 | #if !defined(_WIN32) || defined(UNDER_CE) | 18 | #if !defined(_WIN32) || defined(UNDER_CE) |
18 | static const UInt32 kDosTimeStartYear = 1980; | 19 | static const unsigned kDosTimeStartYear = 1980; |
19 | #endif | 20 | #endif |
20 | static const UInt32 kUnixTimeStartYear = 1970; | 21 | static const unsigned kUnixTimeStartYear = 1970; |
21 | static const UInt64 kUnixTimeOffset = | 22 | static const UInt64 kUnixTimeOffset = |
22 | (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); | 23 | (UInt64)60 * 60 * 24 * (89 + 365 * (UInt32)(kUnixTimeStartYear - kFileTimeStartYear)); |
23 | static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; | 24 | static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; |
24 | 25 | ||
25 | bool DosTime_To_FileTime(UInt32 dosTime, FILETIME &ft) throw() | 26 | bool DosTime_To_FileTime(UInt32 dosTime, FILETIME &ft) throw() |
@@ -30,8 +31,14 @@ bool DosTime_To_FileTime(UInt32 dosTime, FILETIME &ft) throw() | |||
30 | ft.dwLowDateTime = 0; | 31 | ft.dwLowDateTime = 0; |
31 | ft.dwHighDateTime = 0; | 32 | ft.dwHighDateTime = 0; |
32 | UInt64 res; | 33 | UInt64 res; |
33 | if (!GetSecondsSince1601(kDosTimeStartYear + (dosTime >> 25), (dosTime >> 21) & 0xF, (dosTime >> 16) & 0x1F, | 34 | if (!GetSecondsSince1601( |
34 | (dosTime >> 11) & 0x1F, (dosTime >> 5) & 0x3F, (dosTime & 0x1F) * 2, res)) | 35 | kDosTimeStartYear + (unsigned)(dosTime >> 25), |
36 | (unsigned)((dosTime >> 21) & 0xF), | ||
37 | (unsigned)((dosTime >> 16) & 0x1F), | ||
38 | (unsigned)((dosTime >> 11) & 0x1F), | ||
39 | (unsigned)((dosTime >> 5) & 0x3F), | ||
40 | (unsigned)((dosTime & 0x1F)) * 2, | ||
41 | res)) | ||
35 | return false; | 42 | return false; |
36 | res *= kNumTimeQuantumsInSecond; | 43 | res *= kNumTimeQuantumsInSecond; |
37 | ft.dwLowDateTime = (UInt32)res; | 44 | ft.dwLowDateTime = (UInt32)res; |
@@ -77,7 +84,7 @@ bool FileTime_To_DosTime(const FILETIME &ft, UInt32 &dosTime) throw() | |||
77 | 84 | ||
78 | v = (UInt32)v64; | 85 | v = (UInt32)v64; |
79 | 86 | ||
80 | year = (unsigned)(kFileTimeStartYear + v / PERIOD_400 * 400); | 87 | year = kFileTimeStartYear + (unsigned)(v / PERIOD_400 * 400); |
81 | v %= PERIOD_400; | 88 | v %= PERIOD_400; |
82 | 89 | ||
83 | temp = (unsigned)(v / PERIOD_100); | 90 | temp = (unsigned)(v / PERIOD_100); |
@@ -116,7 +123,13 @@ bool FileTime_To_DosTime(const FILETIME &ft, UInt32 &dosTime) throw() | |||
116 | dosTime = kHighDosTime; | 123 | dosTime = kHighDosTime; |
117 | if (year >= 128) | 124 | if (year >= 128) |
118 | return false; | 125 | return false; |
119 | dosTime = (year << 25) | (mon << 21) | (day << 16) | (hour << 11) | (min << 5) | (sec >> 1); | 126 | dosTime = |
127 | ((UInt32)year << 25) | ||
128 | | ((UInt32)mon << 21) | ||
129 | | ((UInt32)day << 16) | ||
130 | | ((UInt32)hour << 11) | ||
131 | | ((UInt32)min << 5) | ||
132 | | ((UInt32)sec >> 1); | ||
120 | #endif | 133 | #endif |
121 | return true; | 134 | return true; |
122 | } | 135 | } |
@@ -226,20 +239,34 @@ bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, | |||
226 | if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 || | 239 | if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 || |
227 | day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) | 240 | day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) |
228 | return false; | 241 | return false; |
229 | UInt32 numYears = year - kFileTimeStartYear; | 242 | const unsigned numYears = year - kFileTimeStartYear; |
230 | UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400; | 243 | UInt32 numDays = (UInt32)((UInt32)numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400); |
231 | Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; | 244 | Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
232 | if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) | 245 | if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) |
233 | ms[1] = 29; | 246 | ms[1] = 29; |
234 | month--; | 247 | month--; |
235 | for (unsigned i = 0; i < month; i++) | 248 | for (unsigned i = 0; i < month; i++) |
236 | numDays += ms[i]; | 249 | numDays += ms[i]; |
237 | numDays += day - 1; | 250 | numDays += (UInt32)(day - 1); |
238 | resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec; | 251 | resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec; |
239 | return true; | 252 | return true; |
240 | } | 253 | } |
241 | 254 | ||
242 | 255 | ||
256 | /* docs: TIME_UTC is not defined on many platforms: | ||
257 | glibc 2.15, macOS 10.13 | ||
258 | FreeBSD 11.0, NetBSD 7.1, OpenBSD 6.0, | ||
259 | Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.3, | ||
260 | Cygwin 2.9, mingw, MSVC 14, Android 9.0. | ||
261 | */ | ||
262 | #if defined(TIME_UTC) | ||
263 | #define ZIP7_USE_timespec_get | ||
264 | // #pragma message("ZIP7_USE_timespec_get") | ||
265 | #elif defined(CLOCK_REALTIME) | ||
266 | #define ZIP7_USE_clock_gettime | ||
267 | // #pragma message("ZIP7_USE_clock_gettime") | ||
268 | #endif | ||
269 | |||
243 | void GetCurUtc_FiTime(CFiTime &ft) throw() | 270 | void GetCurUtc_FiTime(CFiTime &ft) throw() |
244 | { | 271 | { |
245 | #ifdef _WIN32 | 272 | #ifdef _WIN32 |
@@ -257,12 +284,33 @@ void GetCurUtc_FiTime(CFiTime &ft) throw() | |||
257 | #else | 284 | #else |
258 | 285 | ||
259 | FiTime_Clear(ft); | 286 | FiTime_Clear(ft); |
287 | #ifdef ZIP7_USE_timespec_get | ||
288 | timespec_get(&ft, TIME_UTC); | ||
289 | #elif defined ZIP7_USE_clock_gettime | ||
290 | |||
291 | #if defined(_AIX) | ||
292 | { | ||
293 | timespec ts; | ||
294 | clock_gettime(CLOCK_REALTIME, &ts); | ||
295 | ft.tv_sec = ts.tv_sec; | ||
296 | ft.tv_nsec = ts.tv_nsec; | ||
297 | } | ||
298 | #else | ||
299 | clock_gettime(CLOCK_REALTIME, &ft); | ||
300 | #endif | ||
301 | |||
302 | #else | ||
260 | struct timeval now; | 303 | struct timeval now; |
261 | if (gettimeofday(&now, NULL) == 0) | 304 | if (gettimeofday(&now, NULL) == 0) |
262 | { | 305 | { |
263 | ft.tv_sec = now.tv_sec; | 306 | ft.tv_sec = now.tv_sec; |
264 | ft.tv_nsec = now.tv_usec * 1000; | 307 | // timeval::tv_usec can be 64-bit signed in some cases |
308 | // timespec::tv_nsec can be 32-bit signed in some cases | ||
309 | ft.tv_nsec = | ||
310 | (Int32) // to eliminate compiler conversion error | ||
311 | (now.tv_usec * 1000); | ||
265 | } | 312 | } |
313 | #endif | ||
266 | 314 | ||
267 | #endif | 315 | #endif |
268 | } | 316 | } |
@@ -271,12 +319,26 @@ void GetCurUtc_FiTime(CFiTime &ft) throw() | |||
271 | void GetCurUtcFileTime(FILETIME &ft) throw() | 319 | void GetCurUtcFileTime(FILETIME &ft) throw() |
272 | { | 320 | { |
273 | UInt64 v = 0; | 321 | UInt64 v = 0; |
322 | #if defined(ZIP7_USE_timespec_get) || \ | ||
323 | defined(ZIP7_USE_clock_gettime) | ||
324 | timespec ts; | ||
325 | #if defined(ZIP7_USE_timespec_get) | ||
326 | if (timespec_get(&ts, TIME_UTC)) | ||
327 | #else | ||
328 | if (clock_gettime(CLOCK_REALTIME, &ts) == 0) | ||
329 | #endif | ||
330 | { | ||
331 | v = ((UInt64)ts.tv_sec + kUnixTimeOffset) * | ||
332 | kNumTimeQuantumsInSecond + (UInt64)ts.tv_nsec / 100; | ||
333 | } | ||
334 | #else | ||
274 | struct timeval now; | 335 | struct timeval now; |
275 | if (gettimeofday(&now, NULL) == 0) | 336 | if (gettimeofday(&now, NULL) == 0) |
276 | { | 337 | { |
277 | v = ((UInt64)now.tv_sec + kUnixTimeOffset) * | 338 | v = ((UInt64)now.tv_sec + kUnixTimeOffset) * |
278 | kNumTimeQuantumsInSecond + (UInt64)now.tv_usec * 10; | 339 | kNumTimeQuantumsInSecond + (UInt64)now.tv_usec * 10; |
279 | } | 340 | } |
341 | #endif | ||
280 | ft.dwLowDateTime = (DWORD)v; | 342 | ft.dwLowDateTime = (DWORD)v; |
281 | ft.dwHighDateTime = (DWORD)(v >> 32); | 343 | ft.dwHighDateTime = (DWORD)(v >> 32); |
282 | } | 344 | } |
@@ -371,7 +433,7 @@ int Compare_FiTime(const CFiTime *a1, const CFiTime *a2) | |||
371 | return 0; | 433 | return 0; |
372 | } | 434 | } |
373 | 435 | ||
374 | bool FILETIME_To_timespec(const FILETIME &ft, timespec &ts) | 436 | bool FILETIME_To_timespec(const FILETIME &ft, CFiTime &ts) |
375 | { | 437 | { |
376 | UInt32 quantums; | 438 | UInt32 quantums; |
377 | const Int64 sec = NWindows::NTime::FileTime_To_UnixTime64_and_Quantums(ft, quantums); | 439 | const Int64 sec = NWindows::NTime::FileTime_To_UnixTime64_and_Quantums(ft, quantums); |
@@ -380,7 +442,7 @@ bool FILETIME_To_timespec(const FILETIME &ft, timespec &ts) | |||
380 | if (sec2 == sec) | 442 | if (sec2 == sec) |
381 | { | 443 | { |
382 | ts.tv_sec = sec2; | 444 | ts.tv_sec = sec2; |
383 | ts.tv_nsec = (long)(quantums * 100); | 445 | ts.tv_nsec = (Int32)(quantums * 100); |
384 | return true; | 446 | return true; |
385 | } | 447 | } |
386 | return false; | 448 | return false; |