aboutsummaryrefslogtreecommitdiff
path: root/CPP/Windows/TimeUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/Windows/TimeUtils.cpp')
-rw-r--r--CPP/Windows/TimeUtils.cpp90
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 {
13namespace NTime { 14namespace NTime {
14 15
15static const UInt32 kNumTimeQuantumsInSecond = 10000000; 16static const UInt32 kNumTimeQuantumsInSecond = 10000000;
16static const UInt32 kFileTimeStartYear = 1601; 17static const unsigned kFileTimeStartYear = 1601;
17#if !defined(_WIN32) || defined(UNDER_CE) 18#if !defined(_WIN32) || defined(UNDER_CE)
18static const UInt32 kDosTimeStartYear = 1980; 19static const unsigned kDosTimeStartYear = 1980;
19#endif 20#endif
20static const UInt32 kUnixTimeStartYear = 1970; 21static const unsigned kUnixTimeStartYear = 1970;
21static const UInt64 kUnixTimeOffset = 22static const UInt64 kUnixTimeOffset =
22 (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); 23 (UInt64)60 * 60 * 24 * (89 + 365 * (UInt32)(kUnixTimeStartYear - kFileTimeStartYear));
23static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; 24static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond;
24 25
25bool DosTime_To_FileTime(UInt32 dosTime, FILETIME &ft) throw() 26bool 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
243void GetCurUtc_FiTime(CFiTime &ft) throw() 270void 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()
271void GetCurUtcFileTime(FILETIME &ft) throw() 319void 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
374bool FILETIME_To_timespec(const FILETIME &ft, timespec &ts) 436bool 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;