diff options
author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2021-12-27 00:00:00 +0000 |
---|---|---|
committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2022-03-18 15:35:13 +0500 |
commit | f19f813537c7aea1c20749c914e756b54a9c3cf5 (patch) | |
tree | 816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /CPP/Windows/TimeUtils.cpp | |
parent | 98e06a519b63b81986abe76d28887f6984a7732b (diff) | |
download | 7zip-21.07.tar.gz 7zip-21.07.tar.bz2 7zip-21.07.zip |
'21.07'21.07
Diffstat (limited to 'CPP/Windows/TimeUtils.cpp')
-rw-r--r-- | CPP/Windows/TimeUtils.cpp | 234 |
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 | |||
12 | namespace NWindows { | ||
13 | namespace NTime { | ||
14 | |||
15 | static const UInt32 kNumTimeQuantumsInSecond = 10000000; | ||
16 | static const UInt32 kFileTimeStartYear = 1601; | ||
17 | #if !defined(_WIN32) || defined(UNDER_CE) | ||
18 | static const UInt32 kDosTimeStartYear = 1980; | ||
19 | #endif | ||
20 | static const UInt32 kUnixTimeStartYear = 1970; | ||
21 | static const UInt64 kUnixTimeOffset = | ||
22 | (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); | ||
23 | static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; | ||
24 | |||
25 | bool 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 | |||
43 | static const UInt32 kHighDosTime = 0xFF9FBF7D; | ||
44 | static const UInt32 kLowDosTime = 0x210000; | ||
45 | |||
46 | bool 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 | |||
124 | UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw() | ||
125 | { | ||
126 | return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; | ||
127 | } | ||
128 | |||
129 | void 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 | |||
136 | UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw() | ||
137 | { | ||
138 | return (UInt64)((Int64)kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond; | ||
139 | } | ||
140 | |||
141 | bool 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 | |||
160 | Int64 FileTimeToUnixTime64(const FILETIME &ft) throw() | ||
161 | { | ||
162 | UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; | ||
163 | return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; | ||
164 | } | ||
165 | |||
166 | bool 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 | |||
185 | bool 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 | |||
205 | void 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 | }} | ||