1*f6dc9357SAndroid Build Coastguard Worker // Windows/TimeUtils.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #ifndef _WIN32
6*f6dc9357SAndroid Build Coastguard Worker #include <sys/time.h>
7*f6dc9357SAndroid Build Coastguard Worker #include <time.h>
8*f6dc9357SAndroid Build Coastguard Worker #endif
9*f6dc9357SAndroid Build Coastguard Worker
10*f6dc9357SAndroid Build Coastguard Worker #include "Defs.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "TimeUtils.h"
12*f6dc9357SAndroid Build Coastguard Worker
13*f6dc9357SAndroid Build Coastguard Worker namespace NWindows {
14*f6dc9357SAndroid Build Coastguard Worker namespace NTime {
15*f6dc9357SAndroid Build Coastguard Worker
16*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kNumTimeQuantumsInSecond = 10000000;
17*f6dc9357SAndroid Build Coastguard Worker static const unsigned kFileTimeStartYear = 1601;
18*f6dc9357SAndroid Build Coastguard Worker #if !defined(_WIN32) || defined(UNDER_CE)
19*f6dc9357SAndroid Build Coastguard Worker static const unsigned kDosTimeStartYear = 1980;
20*f6dc9357SAndroid Build Coastguard Worker #endif
21*f6dc9357SAndroid Build Coastguard Worker static const unsigned kUnixTimeStartYear = 1970;
22*f6dc9357SAndroid Build Coastguard Worker static const UInt64 kUnixTimeOffset =
23*f6dc9357SAndroid Build Coastguard Worker (UInt64)60 * 60 * 24 * (89 + 365 * (UInt32)(kUnixTimeStartYear - kFileTimeStartYear));
24*f6dc9357SAndroid Build Coastguard Worker static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond;
25*f6dc9357SAndroid Build Coastguard Worker
DosTime_To_FileTime(UInt32 dosTime,FILETIME & ft)26*f6dc9357SAndroid Build Coastguard Worker bool DosTime_To_FileTime(UInt32 dosTime, FILETIME &ft) throw()
27*f6dc9357SAndroid Build Coastguard Worker {
28*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(UNDER_CE)
29*f6dc9357SAndroid Build Coastguard Worker return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft));
30*f6dc9357SAndroid Build Coastguard Worker #else
31*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = 0;
32*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = 0;
33*f6dc9357SAndroid Build Coastguard Worker UInt64 res;
34*f6dc9357SAndroid Build Coastguard Worker if (!GetSecondsSince1601(
35*f6dc9357SAndroid Build Coastguard Worker kDosTimeStartYear + (unsigned)(dosTime >> 25),
36*f6dc9357SAndroid Build Coastguard Worker (unsigned)((dosTime >> 21) & 0xF),
37*f6dc9357SAndroid Build Coastguard Worker (unsigned)((dosTime >> 16) & 0x1F),
38*f6dc9357SAndroid Build Coastguard Worker (unsigned)((dosTime >> 11) & 0x1F),
39*f6dc9357SAndroid Build Coastguard Worker (unsigned)((dosTime >> 5) & 0x3F),
40*f6dc9357SAndroid Build Coastguard Worker (unsigned)((dosTime & 0x1F)) * 2,
41*f6dc9357SAndroid Build Coastguard Worker res))
42*f6dc9357SAndroid Build Coastguard Worker return false;
43*f6dc9357SAndroid Build Coastguard Worker res *= kNumTimeQuantumsInSecond;
44*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = (UInt32)res;
45*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = (UInt32)(res >> 32);
46*f6dc9357SAndroid Build Coastguard Worker return true;
47*f6dc9357SAndroid Build Coastguard Worker #endif
48*f6dc9357SAndroid Build Coastguard Worker }
49*f6dc9357SAndroid Build Coastguard Worker
50*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kHighDosTime = 0xFF9FBF7D;
51*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kLowDosTime = 0x210000;
52*f6dc9357SAndroid Build Coastguard Worker
FileTime_To_DosTime(const FILETIME & ft,UInt32 & dosTime)53*f6dc9357SAndroid Build Coastguard Worker bool FileTime_To_DosTime(const FILETIME &ft, UInt32 &dosTime) throw()
54*f6dc9357SAndroid Build Coastguard Worker {
55*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(UNDER_CE)
56*f6dc9357SAndroid Build Coastguard Worker
57*f6dc9357SAndroid Build Coastguard Worker WORD datePart, timePart;
58*f6dc9357SAndroid Build Coastguard Worker if (!::FileTimeToDosDateTime(&ft, &datePart, &timePart))
59*f6dc9357SAndroid Build Coastguard Worker {
60*f6dc9357SAndroid Build Coastguard Worker dosTime = (ft.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime;
61*f6dc9357SAndroid Build Coastguard Worker return false;
62*f6dc9357SAndroid Build Coastguard Worker }
63*f6dc9357SAndroid Build Coastguard Worker dosTime = (((UInt32)datePart) << 16) + timePart;
64*f6dc9357SAndroid Build Coastguard Worker
65*f6dc9357SAndroid Build Coastguard Worker #else
66*f6dc9357SAndroid Build Coastguard Worker
67*f6dc9357SAndroid Build Coastguard Worker #define PERIOD_4 (4 * 365 + 1)
68*f6dc9357SAndroid Build Coastguard Worker #define PERIOD_100 (PERIOD_4 * 25 - 1)
69*f6dc9357SAndroid Build Coastguard Worker #define PERIOD_400 (PERIOD_100 * 4 + 1)
70*f6dc9357SAndroid Build Coastguard Worker
71*f6dc9357SAndroid Build Coastguard Worker unsigned year, mon, day, hour, min, sec;
72*f6dc9357SAndroid Build Coastguard Worker UInt64 v64 = ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32);
73*f6dc9357SAndroid Build Coastguard Worker Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
74*f6dc9357SAndroid Build Coastguard Worker unsigned temp;
75*f6dc9357SAndroid Build Coastguard Worker UInt32 v;
76*f6dc9357SAndroid Build Coastguard Worker v64 += (kNumTimeQuantumsInSecond * 2 - 1);
77*f6dc9357SAndroid Build Coastguard Worker v64 /= kNumTimeQuantumsInSecond;
78*f6dc9357SAndroid Build Coastguard Worker sec = (unsigned)(v64 % 60);
79*f6dc9357SAndroid Build Coastguard Worker v64 /= 60;
80*f6dc9357SAndroid Build Coastguard Worker min = (unsigned)(v64 % 60);
81*f6dc9357SAndroid Build Coastguard Worker v64 /= 60;
82*f6dc9357SAndroid Build Coastguard Worker hour = (unsigned)(v64 % 24);
83*f6dc9357SAndroid Build Coastguard Worker v64 /= 24;
84*f6dc9357SAndroid Build Coastguard Worker
85*f6dc9357SAndroid Build Coastguard Worker v = (UInt32)v64;
86*f6dc9357SAndroid Build Coastguard Worker
87*f6dc9357SAndroid Build Coastguard Worker year = kFileTimeStartYear + (unsigned)(v / PERIOD_400 * 400);
88*f6dc9357SAndroid Build Coastguard Worker v %= PERIOD_400;
89*f6dc9357SAndroid Build Coastguard Worker
90*f6dc9357SAndroid Build Coastguard Worker temp = (unsigned)(v / PERIOD_100);
91*f6dc9357SAndroid Build Coastguard Worker if (temp == 4)
92*f6dc9357SAndroid Build Coastguard Worker temp = 3;
93*f6dc9357SAndroid Build Coastguard Worker year += temp * 100;
94*f6dc9357SAndroid Build Coastguard Worker v -= temp * PERIOD_100;
95*f6dc9357SAndroid Build Coastguard Worker
96*f6dc9357SAndroid Build Coastguard Worker temp = v / PERIOD_4;
97*f6dc9357SAndroid Build Coastguard Worker if (temp == 25)
98*f6dc9357SAndroid Build Coastguard Worker temp = 24;
99*f6dc9357SAndroid Build Coastguard Worker year += temp * 4;
100*f6dc9357SAndroid Build Coastguard Worker v -= temp * PERIOD_4;
101*f6dc9357SAndroid Build Coastguard Worker
102*f6dc9357SAndroid Build Coastguard Worker temp = v / 365;
103*f6dc9357SAndroid Build Coastguard Worker if (temp == 4)
104*f6dc9357SAndroid Build Coastguard Worker temp = 3;
105*f6dc9357SAndroid Build Coastguard Worker year += temp;
106*f6dc9357SAndroid Build Coastguard Worker v -= temp * 365;
107*f6dc9357SAndroid Build Coastguard Worker
108*f6dc9357SAndroid Build Coastguard Worker if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
109*f6dc9357SAndroid Build Coastguard Worker ms[1] = 29;
110*f6dc9357SAndroid Build Coastguard Worker for (mon = 1; mon <= 12; mon++)
111*f6dc9357SAndroid Build Coastguard Worker {
112*f6dc9357SAndroid Build Coastguard Worker unsigned s = ms[mon - 1];
113*f6dc9357SAndroid Build Coastguard Worker if (v < s)
114*f6dc9357SAndroid Build Coastguard Worker break;
115*f6dc9357SAndroid Build Coastguard Worker v -= s;
116*f6dc9357SAndroid Build Coastguard Worker }
117*f6dc9357SAndroid Build Coastguard Worker day = (unsigned)v + 1;
118*f6dc9357SAndroid Build Coastguard Worker
119*f6dc9357SAndroid Build Coastguard Worker dosTime = kLowDosTime;
120*f6dc9357SAndroid Build Coastguard Worker if (year < kDosTimeStartYear)
121*f6dc9357SAndroid Build Coastguard Worker return false;
122*f6dc9357SAndroid Build Coastguard Worker year -= kDosTimeStartYear;
123*f6dc9357SAndroid Build Coastguard Worker dosTime = kHighDosTime;
124*f6dc9357SAndroid Build Coastguard Worker if (year >= 128)
125*f6dc9357SAndroid Build Coastguard Worker return false;
126*f6dc9357SAndroid Build Coastguard Worker dosTime =
127*f6dc9357SAndroid Build Coastguard Worker ((UInt32)year << 25)
128*f6dc9357SAndroid Build Coastguard Worker | ((UInt32)mon << 21)
129*f6dc9357SAndroid Build Coastguard Worker | ((UInt32)day << 16)
130*f6dc9357SAndroid Build Coastguard Worker | ((UInt32)hour << 11)
131*f6dc9357SAndroid Build Coastguard Worker | ((UInt32)min << 5)
132*f6dc9357SAndroid Build Coastguard Worker | ((UInt32)sec >> 1);
133*f6dc9357SAndroid Build Coastguard Worker #endif
134*f6dc9357SAndroid Build Coastguard Worker return true;
135*f6dc9357SAndroid Build Coastguard Worker }
136*f6dc9357SAndroid Build Coastguard Worker
137*f6dc9357SAndroid Build Coastguard Worker
UtcFileTime_To_LocalDosTime(const FILETIME & utc,UInt32 & dosTime)138*f6dc9357SAndroid Build Coastguard Worker bool UtcFileTime_To_LocalDosTime(const FILETIME &utc, UInt32 &dosTime) throw()
139*f6dc9357SAndroid Build Coastguard Worker {
140*f6dc9357SAndroid Build Coastguard Worker FILETIME loc = { 0, 0 };
141*f6dc9357SAndroid Build Coastguard Worker const UInt64 u1 = FILETIME_To_UInt64(utc);
142*f6dc9357SAndroid Build Coastguard Worker const UInt64 kDelta = ((UInt64)1 << 41); // it's larger than quantums in 1 sec.
143*f6dc9357SAndroid Build Coastguard Worker if (u1 >= kDelta)
144*f6dc9357SAndroid Build Coastguard Worker {
145*f6dc9357SAndroid Build Coastguard Worker if (!FileTimeToLocalFileTime(&utc, &loc))
146*f6dc9357SAndroid Build Coastguard Worker loc = utc;
147*f6dc9357SAndroid Build Coastguard Worker else
148*f6dc9357SAndroid Build Coastguard Worker {
149*f6dc9357SAndroid Build Coastguard Worker const UInt64 u2 = FILETIME_To_UInt64(loc);
150*f6dc9357SAndroid Build Coastguard Worker const UInt64 delta = u1 < u2 ? (u2 - u1) : (u1 - u2);
151*f6dc9357SAndroid Build Coastguard Worker if (delta > kDelta) // if FileTimeToLocalFileTime() overflow, we use UTC time
152*f6dc9357SAndroid Build Coastguard Worker loc = utc;
153*f6dc9357SAndroid Build Coastguard Worker }
154*f6dc9357SAndroid Build Coastguard Worker }
155*f6dc9357SAndroid Build Coastguard Worker return FileTime_To_DosTime(loc, dosTime);
156*f6dc9357SAndroid Build Coastguard Worker }
157*f6dc9357SAndroid Build Coastguard Worker
UnixTime_To_FileTime64(UInt32 unixTime)158*f6dc9357SAndroid Build Coastguard Worker UInt64 UnixTime_To_FileTime64(UInt32 unixTime) throw()
159*f6dc9357SAndroid Build Coastguard Worker {
160*f6dc9357SAndroid Build Coastguard Worker return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond;
161*f6dc9357SAndroid Build Coastguard Worker }
162*f6dc9357SAndroid Build Coastguard Worker
UnixTime_To_FileTime(UInt32 unixTime,FILETIME & ft)163*f6dc9357SAndroid Build Coastguard Worker void UnixTime_To_FileTime(UInt32 unixTime, FILETIME &ft) throw()
164*f6dc9357SAndroid Build Coastguard Worker {
165*f6dc9357SAndroid Build Coastguard Worker const UInt64 v = UnixTime_To_FileTime64(unixTime);
166*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = (DWORD)v;
167*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = (DWORD)(v >> 32);
168*f6dc9357SAndroid Build Coastguard Worker }
169*f6dc9357SAndroid Build Coastguard Worker
UnixTime64_To_FileTime64(Int64 unixTime)170*f6dc9357SAndroid Build Coastguard Worker UInt64 UnixTime64_To_FileTime64(Int64 unixTime) throw()
171*f6dc9357SAndroid Build Coastguard Worker {
172*f6dc9357SAndroid Build Coastguard Worker return (UInt64)((Int64)kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond;
173*f6dc9357SAndroid Build Coastguard Worker }
174*f6dc9357SAndroid Build Coastguard Worker
175*f6dc9357SAndroid Build Coastguard Worker
UnixTime64_To_FileTime64(Int64 unixTime,UInt64 & fileTime)176*f6dc9357SAndroid Build Coastguard Worker bool UnixTime64_To_FileTime64(Int64 unixTime, UInt64 &fileTime) throw()
177*f6dc9357SAndroid Build Coastguard Worker {
178*f6dc9357SAndroid Build Coastguard Worker if (unixTime > (Int64)(kNumSecondsInFileTime - kUnixTimeOffset))
179*f6dc9357SAndroid Build Coastguard Worker {
180*f6dc9357SAndroid Build Coastguard Worker fileTime = (UInt64)(Int64)-1;
181*f6dc9357SAndroid Build Coastguard Worker return false;
182*f6dc9357SAndroid Build Coastguard Worker }
183*f6dc9357SAndroid Build Coastguard Worker if (unixTime < -(Int64)kUnixTimeOffset)
184*f6dc9357SAndroid Build Coastguard Worker {
185*f6dc9357SAndroid Build Coastguard Worker fileTime = 0;
186*f6dc9357SAndroid Build Coastguard Worker return false;
187*f6dc9357SAndroid Build Coastguard Worker }
188*f6dc9357SAndroid Build Coastguard Worker fileTime = UnixTime64_To_FileTime64(unixTime);
189*f6dc9357SAndroid Build Coastguard Worker return true;
190*f6dc9357SAndroid Build Coastguard Worker }
191*f6dc9357SAndroid Build Coastguard Worker
192*f6dc9357SAndroid Build Coastguard Worker
UnixTime64_To_FileTime(Int64 unixTime,FILETIME & ft)193*f6dc9357SAndroid Build Coastguard Worker bool UnixTime64_To_FileTime(Int64 unixTime, FILETIME &ft) throw()
194*f6dc9357SAndroid Build Coastguard Worker {
195*f6dc9357SAndroid Build Coastguard Worker UInt64 v;
196*f6dc9357SAndroid Build Coastguard Worker const bool res = UnixTime64_To_FileTime64(unixTime, v);
197*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = (DWORD)v;
198*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = (DWORD)(v >> 32);
199*f6dc9357SAndroid Build Coastguard Worker return res;
200*f6dc9357SAndroid Build Coastguard Worker }
201*f6dc9357SAndroid Build Coastguard Worker
202*f6dc9357SAndroid Build Coastguard Worker
FileTime_To_UnixTime64(const FILETIME & ft)203*f6dc9357SAndroid Build Coastguard Worker Int64 FileTime_To_UnixTime64(const FILETIME &ft) throw()
204*f6dc9357SAndroid Build Coastguard Worker {
205*f6dc9357SAndroid Build Coastguard Worker const UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
206*f6dc9357SAndroid Build Coastguard Worker return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset;
207*f6dc9357SAndroid Build Coastguard Worker }
208*f6dc9357SAndroid Build Coastguard Worker
FileTime_To_UnixTime64_and_Quantums(const FILETIME & ft,UInt32 & quantums)209*f6dc9357SAndroid Build Coastguard Worker Int64 FileTime_To_UnixTime64_and_Quantums(const FILETIME &ft, UInt32 &quantums) throw()
210*f6dc9357SAndroid Build Coastguard Worker {
211*f6dc9357SAndroid Build Coastguard Worker const UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
212*f6dc9357SAndroid Build Coastguard Worker quantums = (UInt32)(winTime % kNumTimeQuantumsInSecond);
213*f6dc9357SAndroid Build Coastguard Worker return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset;
214*f6dc9357SAndroid Build Coastguard Worker }
215*f6dc9357SAndroid Build Coastguard Worker
FileTime_To_UnixTime(const FILETIME & ft,UInt32 & unixTime)216*f6dc9357SAndroid Build Coastguard Worker bool FileTime_To_UnixTime(const FILETIME &ft, UInt32 &unixTime) throw()
217*f6dc9357SAndroid Build Coastguard Worker {
218*f6dc9357SAndroid Build Coastguard Worker UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
219*f6dc9357SAndroid Build Coastguard Worker winTime /= kNumTimeQuantumsInSecond;
220*f6dc9357SAndroid Build Coastguard Worker if (winTime < kUnixTimeOffset)
221*f6dc9357SAndroid Build Coastguard Worker {
222*f6dc9357SAndroid Build Coastguard Worker unixTime = 0;
223*f6dc9357SAndroid Build Coastguard Worker return false;
224*f6dc9357SAndroid Build Coastguard Worker }
225*f6dc9357SAndroid Build Coastguard Worker winTime -= kUnixTimeOffset;
226*f6dc9357SAndroid Build Coastguard Worker if (winTime > (UInt32)0xFFFFFFFF)
227*f6dc9357SAndroid Build Coastguard Worker {
228*f6dc9357SAndroid Build Coastguard Worker unixTime = (UInt32)0xFFFFFFFF;
229*f6dc9357SAndroid Build Coastguard Worker return false;
230*f6dc9357SAndroid Build Coastguard Worker }
231*f6dc9357SAndroid Build Coastguard Worker unixTime = (UInt32)winTime;
232*f6dc9357SAndroid Build Coastguard Worker return true;
233*f6dc9357SAndroid Build Coastguard Worker }
234*f6dc9357SAndroid Build Coastguard Worker
GetSecondsSince1601(unsigned year,unsigned month,unsigned day,unsigned hour,unsigned min,unsigned sec,UInt64 & resSeconds)235*f6dc9357SAndroid Build Coastguard Worker bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,
236*f6dc9357SAndroid Build Coastguard Worker unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw()
237*f6dc9357SAndroid Build Coastguard Worker {
238*f6dc9357SAndroid Build Coastguard Worker resSeconds = 0;
239*f6dc9357SAndroid Build Coastguard Worker if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 ||
240*f6dc9357SAndroid Build Coastguard Worker day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59)
241*f6dc9357SAndroid Build Coastguard Worker return false;
242*f6dc9357SAndroid Build Coastguard Worker const unsigned numYears = year - kFileTimeStartYear;
243*f6dc9357SAndroid Build Coastguard Worker UInt32 numDays = (UInt32)((UInt32)numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400);
244*f6dc9357SAndroid Build Coastguard Worker Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
245*f6dc9357SAndroid Build Coastguard Worker if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
246*f6dc9357SAndroid Build Coastguard Worker ms[1] = 29;
247*f6dc9357SAndroid Build Coastguard Worker month--;
248*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < month; i++)
249*f6dc9357SAndroid Build Coastguard Worker numDays += ms[i];
250*f6dc9357SAndroid Build Coastguard Worker numDays += (UInt32)(day - 1);
251*f6dc9357SAndroid Build Coastguard Worker resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec;
252*f6dc9357SAndroid Build Coastguard Worker return true;
253*f6dc9357SAndroid Build Coastguard Worker }
254*f6dc9357SAndroid Build Coastguard Worker
255*f6dc9357SAndroid Build Coastguard Worker
256*f6dc9357SAndroid Build Coastguard Worker /* docs: TIME_UTC is not defined on many platforms:
257*f6dc9357SAndroid Build Coastguard Worker glibc 2.15, macOS 10.13
258*f6dc9357SAndroid Build Coastguard Worker FreeBSD 11.0, NetBSD 7.1, OpenBSD 6.0,
259*f6dc9357SAndroid Build Coastguard Worker Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.3,
260*f6dc9357SAndroid Build Coastguard Worker Cygwin 2.9, mingw, MSVC 14, Android 9.0.
261*f6dc9357SAndroid Build Coastguard Worker */
262*f6dc9357SAndroid Build Coastguard Worker #if defined(TIME_UTC)
263*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_USE_timespec_get
264*f6dc9357SAndroid Build Coastguard Worker // #pragma message("ZIP7_USE_timespec_get")
265*f6dc9357SAndroid Build Coastguard Worker #elif defined(CLOCK_REALTIME)
266*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_USE_clock_gettime
267*f6dc9357SAndroid Build Coastguard Worker // #pragma message("ZIP7_USE_clock_gettime")
268*f6dc9357SAndroid Build Coastguard Worker #endif
269*f6dc9357SAndroid Build Coastguard Worker
GetCurUtc_FiTime(CFiTime & ft)270*f6dc9357SAndroid Build Coastguard Worker void GetCurUtc_FiTime(CFiTime &ft) throw()
271*f6dc9357SAndroid Build Coastguard Worker {
272*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
273*f6dc9357SAndroid Build Coastguard Worker
274*f6dc9357SAndroid Build Coastguard Worker // Both variants provide same low resolution on WinXP: about 15 ms.
275*f6dc9357SAndroid Build Coastguard Worker // But GetSystemTimeAsFileTime is much faster.
276*f6dc9357SAndroid Build Coastguard Worker #ifdef UNDER_CE
277*f6dc9357SAndroid Build Coastguard Worker SYSTEMTIME st;
278*f6dc9357SAndroid Build Coastguard Worker GetSystemTime(&st);
279*f6dc9357SAndroid Build Coastguard Worker SystemTimeToFileTime(&st, &ft);
280*f6dc9357SAndroid Build Coastguard Worker #else
281*f6dc9357SAndroid Build Coastguard Worker GetSystemTimeAsFileTime(&ft);
282*f6dc9357SAndroid Build Coastguard Worker #endif
283*f6dc9357SAndroid Build Coastguard Worker
284*f6dc9357SAndroid Build Coastguard Worker #else
285*f6dc9357SAndroid Build Coastguard Worker
286*f6dc9357SAndroid Build Coastguard Worker FiTime_Clear(ft);
287*f6dc9357SAndroid Build Coastguard Worker #ifdef ZIP7_USE_timespec_get
288*f6dc9357SAndroid Build Coastguard Worker timespec_get(&ft, TIME_UTC);
289*f6dc9357SAndroid Build Coastguard Worker #elif defined ZIP7_USE_clock_gettime
290*f6dc9357SAndroid Build Coastguard Worker
291*f6dc9357SAndroid Build Coastguard Worker #if defined(_AIX)
292*f6dc9357SAndroid Build Coastguard Worker {
293*f6dc9357SAndroid Build Coastguard Worker timespec ts;
294*f6dc9357SAndroid Build Coastguard Worker clock_gettime(CLOCK_REALTIME, &ts);
295*f6dc9357SAndroid Build Coastguard Worker ft.tv_sec = ts.tv_sec;
296*f6dc9357SAndroid Build Coastguard Worker ft.tv_nsec = ts.tv_nsec;
297*f6dc9357SAndroid Build Coastguard Worker }
298*f6dc9357SAndroid Build Coastguard Worker #else
299*f6dc9357SAndroid Build Coastguard Worker clock_gettime(CLOCK_REALTIME, &ft);
300*f6dc9357SAndroid Build Coastguard Worker #endif
301*f6dc9357SAndroid Build Coastguard Worker
302*f6dc9357SAndroid Build Coastguard Worker #else
303*f6dc9357SAndroid Build Coastguard Worker struct timeval now;
304*f6dc9357SAndroid Build Coastguard Worker if (gettimeofday(&now, NULL) == 0)
305*f6dc9357SAndroid Build Coastguard Worker {
306*f6dc9357SAndroid Build Coastguard Worker ft.tv_sec = now.tv_sec;
307*f6dc9357SAndroid Build Coastguard Worker // timeval::tv_usec can be 64-bit signed in some cases
308*f6dc9357SAndroid Build Coastguard Worker // timespec::tv_nsec can be 32-bit signed in some cases
309*f6dc9357SAndroid Build Coastguard Worker ft.tv_nsec =
310*f6dc9357SAndroid Build Coastguard Worker (Int32) // to eliminate compiler conversion error
311*f6dc9357SAndroid Build Coastguard Worker (now.tv_usec * 1000);
312*f6dc9357SAndroid Build Coastguard Worker }
313*f6dc9357SAndroid Build Coastguard Worker #endif
314*f6dc9357SAndroid Build Coastguard Worker
315*f6dc9357SAndroid Build Coastguard Worker #endif
316*f6dc9357SAndroid Build Coastguard Worker }
317*f6dc9357SAndroid Build Coastguard Worker
318*f6dc9357SAndroid Build Coastguard Worker #ifndef _WIN32
GetCurUtcFileTime(FILETIME & ft)319*f6dc9357SAndroid Build Coastguard Worker void GetCurUtcFileTime(FILETIME &ft) throw()
320*f6dc9357SAndroid Build Coastguard Worker {
321*f6dc9357SAndroid Build Coastguard Worker UInt64 v = 0;
322*f6dc9357SAndroid Build Coastguard Worker #if defined(ZIP7_USE_timespec_get) || \
323*f6dc9357SAndroid Build Coastguard Worker defined(ZIP7_USE_clock_gettime)
324*f6dc9357SAndroid Build Coastguard Worker timespec ts;
325*f6dc9357SAndroid Build Coastguard Worker #if defined(ZIP7_USE_timespec_get)
326*f6dc9357SAndroid Build Coastguard Worker if (timespec_get(&ts, TIME_UTC))
327*f6dc9357SAndroid Build Coastguard Worker #else
328*f6dc9357SAndroid Build Coastguard Worker if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
329*f6dc9357SAndroid Build Coastguard Worker #endif
330*f6dc9357SAndroid Build Coastguard Worker {
331*f6dc9357SAndroid Build Coastguard Worker v = ((UInt64)ts.tv_sec + kUnixTimeOffset) *
332*f6dc9357SAndroid Build Coastguard Worker kNumTimeQuantumsInSecond + (UInt64)ts.tv_nsec / 100;
333*f6dc9357SAndroid Build Coastguard Worker }
334*f6dc9357SAndroid Build Coastguard Worker #else
335*f6dc9357SAndroid Build Coastguard Worker struct timeval now;
336*f6dc9357SAndroid Build Coastguard Worker if (gettimeofday(&now, NULL) == 0)
337*f6dc9357SAndroid Build Coastguard Worker {
338*f6dc9357SAndroid Build Coastguard Worker v = ((UInt64)now.tv_sec + kUnixTimeOffset) *
339*f6dc9357SAndroid Build Coastguard Worker kNumTimeQuantumsInSecond + (UInt64)now.tv_usec * 10;
340*f6dc9357SAndroid Build Coastguard Worker }
341*f6dc9357SAndroid Build Coastguard Worker #endif
342*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = (DWORD)v;
343*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = (DWORD)(v >> 32);
344*f6dc9357SAndroid Build Coastguard Worker }
345*f6dc9357SAndroid Build Coastguard Worker #endif
346*f6dc9357SAndroid Build Coastguard Worker
347*f6dc9357SAndroid Build Coastguard Worker
348*f6dc9357SAndroid Build Coastguard Worker }}
349*f6dc9357SAndroid Build Coastguard Worker
350*f6dc9357SAndroid Build Coastguard Worker
351*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
352*f6dc9357SAndroid Build Coastguard Worker
353*f6dc9357SAndroid Build Coastguard Worker /*
354*f6dc9357SAndroid Build Coastguard Worker void FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec)
355*f6dc9357SAndroid Build Coastguard Worker {
356*f6dc9357SAndroid Build Coastguard Worker if (prec == k_PropVar_TimePrec_0
357*f6dc9357SAndroid Build Coastguard Worker || prec == k_PropVar_TimePrec_HighPrec
358*f6dc9357SAndroid Build Coastguard Worker || prec >= k_PropVar_TimePrec_100ns)
359*f6dc9357SAndroid Build Coastguard Worker return;
360*f6dc9357SAndroid Build Coastguard Worker UInt64 v = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
361*f6dc9357SAndroid Build Coastguard Worker
362*f6dc9357SAndroid Build Coastguard Worker int numDigits = (int)prec - (int)k_PropVar_TimePrec_Base;
363*f6dc9357SAndroid Build Coastguard Worker UInt32 d;
364*f6dc9357SAndroid Build Coastguard Worker if (prec == k_PropVar_TimePrec_DOS)
365*f6dc9357SAndroid Build Coastguard Worker {
366*f6dc9357SAndroid Build Coastguard Worker // we round up as windows DosDateTimeToFileTime()
367*f6dc9357SAndroid Build Coastguard Worker v += NWindows::NTime::kNumTimeQuantumsInSecond * 2 - 1;
368*f6dc9357SAndroid Build Coastguard Worker d = NWindows::NTime::kNumTimeQuantumsInSecond * 2;
369*f6dc9357SAndroid Build Coastguard Worker }
370*f6dc9357SAndroid Build Coastguard Worker else
371*f6dc9357SAndroid Build Coastguard Worker {
372*f6dc9357SAndroid Build Coastguard Worker if (prec == k_PropVar_TimePrec_Unix)
373*f6dc9357SAndroid Build Coastguard Worker numDigits = 0;
374*f6dc9357SAndroid Build Coastguard Worker else if (numDigits < 0)
375*f6dc9357SAndroid Build Coastguard Worker return;
376*f6dc9357SAndroid Build Coastguard Worker d = 1;
377*f6dc9357SAndroid Build Coastguard Worker for (unsigned k = numDigits; k < 7; k++)
378*f6dc9357SAndroid Build Coastguard Worker d *= 10;
379*f6dc9357SAndroid Build Coastguard Worker }
380*f6dc9357SAndroid Build Coastguard Worker v /= d;
381*f6dc9357SAndroid Build Coastguard Worker v *= d;
382*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = (DWORD)v;
383*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = (DWORD)(v >> 32);
384*f6dc9357SAndroid Build Coastguard Worker }
385*f6dc9357SAndroid Build Coastguard Worker */
386*f6dc9357SAndroid Build Coastguard Worker
387*f6dc9357SAndroid Build Coastguard Worker #else
388*f6dc9357SAndroid Build Coastguard Worker
389*f6dc9357SAndroid Build Coastguard Worker /*
390*f6dc9357SAndroid Build Coastguard Worker void FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec)
391*f6dc9357SAndroid Build Coastguard Worker {
392*f6dc9357SAndroid Build Coastguard Worker if (prec >= k_PropVar_TimePrec_1ns
393*f6dc9357SAndroid Build Coastguard Worker || prec == k_PropVar_TimePrec_HighPrec)
394*f6dc9357SAndroid Build Coastguard Worker return;
395*f6dc9357SAndroid Build Coastguard Worker
396*f6dc9357SAndroid Build Coastguard Worker int numDigits = (int)prec - (int)k_PropVar_TimePrec_Base;
397*f6dc9357SAndroid Build Coastguard Worker UInt32 d;
398*f6dc9357SAndroid Build Coastguard Worker if (prec == k_PropVar_TimePrec_Unix ||
399*f6dc9357SAndroid Build Coastguard Worker prec == (int)k_PropVar_TimePrec_Base)
400*f6dc9357SAndroid Build Coastguard Worker {
401*f6dc9357SAndroid Build Coastguard Worker ft.tv_nsec = 0;
402*f6dc9357SAndroid Build Coastguard Worker return;
403*f6dc9357SAndroid Build Coastguard Worker }
404*f6dc9357SAndroid Build Coastguard Worker if (prec == k_PropVar_TimePrec_DOS)
405*f6dc9357SAndroid Build Coastguard Worker {
406*f6dc9357SAndroid Build Coastguard Worker // we round up as windows DosDateTimeToFileTime()
407*f6dc9357SAndroid Build Coastguard Worker const unsigned sec1 = (ft.tv_sec & 1);
408*f6dc9357SAndroid Build Coastguard Worker if (ft.tv_nsec == 0 && sec1 == 0)
409*f6dc9357SAndroid Build Coastguard Worker return;
410*f6dc9357SAndroid Build Coastguard Worker ft.tv_nsec = 0;
411*f6dc9357SAndroid Build Coastguard Worker ft.tv_sec += 2 - sec1;
412*f6dc9357SAndroid Build Coastguard Worker return;
413*f6dc9357SAndroid Build Coastguard Worker }
414*f6dc9357SAndroid Build Coastguard Worker {
415*f6dc9357SAndroid Build Coastguard Worker if (prec == k_PropVar_TimePrec_0
416*f6dc9357SAndroid Build Coastguard Worker || numDigits < 0)
417*f6dc9357SAndroid Build Coastguard Worker numDigits = 7;
418*f6dc9357SAndroid Build Coastguard Worker d = 1;
419*f6dc9357SAndroid Build Coastguard Worker for (unsigned k = numDigits; k < 9; k++)
420*f6dc9357SAndroid Build Coastguard Worker d *= 10;
421*f6dc9357SAndroid Build Coastguard Worker ft.tv_nsec /= d;
422*f6dc9357SAndroid Build Coastguard Worker ft.tv_nsec *= d;
423*f6dc9357SAndroid Build Coastguard Worker }
424*f6dc9357SAndroid Build Coastguard Worker }
425*f6dc9357SAndroid Build Coastguard Worker */
426*f6dc9357SAndroid Build Coastguard Worker
Compare_FiTime(const CFiTime * a1,const CFiTime * a2)427*f6dc9357SAndroid Build Coastguard Worker int Compare_FiTime(const CFiTime *a1, const CFiTime *a2)
428*f6dc9357SAndroid Build Coastguard Worker {
429*f6dc9357SAndroid Build Coastguard Worker if (a1->tv_sec < a2->tv_sec) return -1;
430*f6dc9357SAndroid Build Coastguard Worker if (a1->tv_sec > a2->tv_sec) return 1;
431*f6dc9357SAndroid Build Coastguard Worker if (a1->tv_nsec < a2->tv_nsec) return -1;
432*f6dc9357SAndroid Build Coastguard Worker if (a1->tv_nsec > a2->tv_nsec) return 1;
433*f6dc9357SAndroid Build Coastguard Worker return 0;
434*f6dc9357SAndroid Build Coastguard Worker }
435*f6dc9357SAndroid Build Coastguard Worker
FILETIME_To_timespec(const FILETIME & ft,CFiTime & ts)436*f6dc9357SAndroid Build Coastguard Worker bool FILETIME_To_timespec(const FILETIME &ft, CFiTime &ts)
437*f6dc9357SAndroid Build Coastguard Worker {
438*f6dc9357SAndroid Build Coastguard Worker UInt32 quantums;
439*f6dc9357SAndroid Build Coastguard Worker const Int64 sec = NWindows::NTime::FileTime_To_UnixTime64_and_Quantums(ft, quantums);
440*f6dc9357SAndroid Build Coastguard Worker // time_t is long
441*f6dc9357SAndroid Build Coastguard Worker const time_t sec2 = (time_t)sec;
442*f6dc9357SAndroid Build Coastguard Worker if (sec2 == sec)
443*f6dc9357SAndroid Build Coastguard Worker {
444*f6dc9357SAndroid Build Coastguard Worker ts.tv_sec = sec2;
445*f6dc9357SAndroid Build Coastguard Worker ts.tv_nsec = (Int32)(quantums * 100);
446*f6dc9357SAndroid Build Coastguard Worker return true;
447*f6dc9357SAndroid Build Coastguard Worker }
448*f6dc9357SAndroid Build Coastguard Worker return false;
449*f6dc9357SAndroid Build Coastguard Worker }
450*f6dc9357SAndroid Build Coastguard Worker
FiTime_To_FILETIME_ns100(const CFiTime & ts,FILETIME & ft,unsigned & ns100)451*f6dc9357SAndroid Build Coastguard Worker void FiTime_To_FILETIME_ns100(const CFiTime &ts, FILETIME &ft, unsigned &ns100)
452*f6dc9357SAndroid Build Coastguard Worker {
453*f6dc9357SAndroid Build Coastguard Worker const UInt64 v = NWindows::NTime::UnixTime64_To_FileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100);
454*f6dc9357SAndroid Build Coastguard Worker ns100 = (unsigned)((UInt64)ts.tv_nsec % 100);
455*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = (DWORD)v;
456*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = (DWORD)(v >> 32);
457*f6dc9357SAndroid Build Coastguard Worker }
458*f6dc9357SAndroid Build Coastguard Worker
FiTime_To_FILETIME(const CFiTime & ts,FILETIME & ft)459*f6dc9357SAndroid Build Coastguard Worker void FiTime_To_FILETIME(const CFiTime &ts, FILETIME &ft)
460*f6dc9357SAndroid Build Coastguard Worker {
461*f6dc9357SAndroid Build Coastguard Worker const UInt64 v = NWindows::NTime::UnixTime64_To_FileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100);
462*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = (DWORD)v;
463*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = (DWORD)(v >> 32);
464*f6dc9357SAndroid Build Coastguard Worker }
465*f6dc9357SAndroid Build Coastguard Worker
466*f6dc9357SAndroid Build Coastguard Worker #endif
467