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.cpp234
1 files changed, 234 insertions, 0 deletions
diff --git a/CPP/Windows/TimeUtils.cpp b/CPP/Windows/TimeUtils.cpp
new file mode 100644
index 0000000..1f1335f
--- /dev/null
+++ b/CPP/Windows/TimeUtils.cpp
@@ -0,0 +1,234 @@
1// Windows/TimeUtils.cpp
2
3#include "StdAfx.h"
4
5#ifndef _WIN32
6#include <sys/time.h>
7#endif
8
9#include "Defs.h"
10#include "TimeUtils.h"
11
12namespace NWindows {
13namespace NTime {
14
15static const UInt32 kNumTimeQuantumsInSecond = 10000000;
16static const UInt32 kFileTimeStartYear = 1601;
17#if !defined(_WIN32) || defined(UNDER_CE)
18static const UInt32 kDosTimeStartYear = 1980;
19#endif
20static const UInt32 kUnixTimeStartYear = 1970;
21static const UInt64 kUnixTimeOffset =
22 (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear));
23static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond;
24
25bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) throw()
26{
27 #if defined(_WIN32) && !defined(UNDER_CE)
28 return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft));
29 #else
30 ft.dwLowDateTime = 0;
31 ft.dwHighDateTime = 0;
32 UInt64 res;
33 if (!GetSecondsSince1601(kDosTimeStartYear + (dosTime >> 25), (dosTime >> 21) & 0xF, (dosTime >> 16) & 0x1F,
34 (dosTime >> 11) & 0x1F, (dosTime >> 5) & 0x3F, (dosTime & 0x1F) * 2, res))
35 return false;
36 res *= kNumTimeQuantumsInSecond;
37 ft.dwLowDateTime = (UInt32)res;
38 ft.dwHighDateTime = (UInt32)(res >> 32);
39 return true;
40 #endif
41}
42
43static const UInt32 kHighDosTime = 0xFF9FBF7D;
44static const UInt32 kLowDosTime = 0x210000;
45
46bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw()
47{
48 #if defined(_WIN32) && !defined(UNDER_CE)
49
50 WORD datePart, timePart;
51 if (!::FileTimeToDosDateTime(&ft, &datePart, &timePart))
52 {
53 dosTime = (ft.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime;
54 return false;
55 }
56 dosTime = (((UInt32)datePart) << 16) + timePart;
57
58 #else
59
60#define PERIOD_4 (4 * 365 + 1)
61#define PERIOD_100 (PERIOD_4 * 25 - 1)
62#define PERIOD_400 (PERIOD_100 * 4 + 1)
63
64 unsigned year, mon, day, hour, min, sec;
65 UInt64 v64 = ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32);
66 Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
67 unsigned temp;
68 UInt32 v;
69 v64 += (kNumTimeQuantumsInSecond * 2 - 1);
70 v64 /= kNumTimeQuantumsInSecond;
71 sec = (unsigned)(v64 % 60);
72 v64 /= 60;
73 min = (unsigned)(v64 % 60);
74 v64 /= 60;
75 hour = (unsigned)(v64 % 24);
76 v64 /= 24;
77
78 v = (UInt32)v64;
79
80 year = (unsigned)(kFileTimeStartYear + v / PERIOD_400 * 400);
81 v %= PERIOD_400;
82
83 temp = (unsigned)(v / PERIOD_100);
84 if (temp == 4)
85 temp = 3;
86 year += temp * 100;
87 v -= temp * PERIOD_100;
88
89 temp = v / PERIOD_4;
90 if (temp == 25)
91 temp = 24;
92 year += temp * 4;
93 v -= temp * PERIOD_4;
94
95 temp = v / 365;
96 if (temp == 4)
97 temp = 3;
98 year += temp;
99 v -= temp * 365;
100
101 if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
102 ms[1] = 29;
103 for (mon = 1; mon <= 12; mon++)
104 {
105 unsigned s = ms[mon - 1];
106 if (v < s)
107 break;
108 v -= s;
109 }
110 day = (unsigned)v + 1;
111
112 dosTime = kLowDosTime;
113 if (year < kDosTimeStartYear)
114 return false;
115 year -= kDosTimeStartYear;
116 dosTime = kHighDosTime;
117 if (year >= 128)
118 return false;
119 dosTime = (year << 25) | (mon << 21) | (day << 16) | (hour << 11) | (min << 5) | (sec >> 1);
120 #endif
121 return true;
122}
123
124UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw()
125{
126 return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond;
127}
128
129void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) throw()
130{
131 UInt64 v = UnixTimeToFileTime64(unixTime);
132 ft.dwLowDateTime = (DWORD)v;
133 ft.dwHighDateTime = (DWORD)(v >> 32);
134}
135
136UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw()
137{
138 return (UInt64)((Int64)kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond;
139}
140
141bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw()
142{
143 if (unixTime > (Int64)(kNumSecondsInFileTime - kUnixTimeOffset))
144 {
145 ft.dwLowDateTime = ft.dwHighDateTime = (UInt32)(Int32)-1;
146 return false;
147 }
148 Int64 v = (Int64)kUnixTimeOffset + unixTime;
149 if (v < 0)
150 {
151 ft.dwLowDateTime = ft.dwHighDateTime = 0;
152 return false;
153 }
154 UInt64 v2 = (UInt64)v * kNumTimeQuantumsInSecond;
155 ft.dwLowDateTime = (DWORD)v2;
156 ft.dwHighDateTime = (DWORD)(v2 >> 32);
157 return true;
158}
159
160Int64 FileTimeToUnixTime64(const FILETIME &ft) throw()
161{
162 UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
163 return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset;
164}
165
166bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) throw()
167{
168 UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
169 winTime /= kNumTimeQuantumsInSecond;
170 if (winTime < kUnixTimeOffset)
171 {
172 unixTime = 0;
173 return false;
174 }
175 winTime -= kUnixTimeOffset;
176 if (winTime > 0xFFFFFFFF)
177 {
178 unixTime = 0xFFFFFFFF;
179 return false;
180 }
181 unixTime = (UInt32)winTime;
182 return true;
183}
184
185bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,
186 unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw()
187{
188 resSeconds = 0;
189 if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 ||
190 day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59)
191 return false;
192 UInt32 numYears = year - kFileTimeStartYear;
193 UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400;
194 Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
195 if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
196 ms[1] = 29;
197 month--;
198 for (unsigned i = 0; i < month; i++)
199 numDays += ms[i];
200 numDays += day - 1;
201 resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec;
202 return true;
203}
204
205void GetCurUtcFileTime(FILETIME &ft) throw()
206{
207 // Both variants provide same low resolution on WinXP: about 15 ms.
208 // But GetSystemTimeAsFileTime is much faster.
209 #ifdef _WIN32
210
211 #ifdef UNDER_CE
212 SYSTEMTIME st;
213 GetSystemTime(&st);
214 SystemTimeToFileTime(&st, &ft);
215 #else
216 GetSystemTimeAsFileTime(&ft);
217 #endif
218
219 #else
220
221 UInt64 v = 0;
222 struct timeval now;
223 if (gettimeofday(&now, 0 ) == 0)
224 {
225 v = ((UInt64)now.tv_sec + kUnixTimeOffset) *
226 kNumTimeQuantumsInSecond + (UInt64)now.tv_usec * 10;
227 }
228 ft.dwLowDateTime = (DWORD)v;
229 ft.dwHighDateTime = (DWORD)(v >> 32);
230
231 #endif
232}
233
234}}