Line | Count | Source (jump to first uncovered line) |
1 | | #include "rar.hpp" |
2 | | |
3 | | void RarTime::GetLocal(RarLocalTime *lt) |
4 | 83 | { |
5 | | #ifdef _WIN_ALL |
6 | | FILETIME ft; |
7 | | GetWinFT(&ft); |
8 | | FILETIME lft; |
9 | | |
10 | | if (WinNT() < WNT_VISTA) |
11 | | { |
12 | | // SystemTimeToTzSpecificLocalTime based code produces 1 hour error on XP. |
13 | | FileTimeToLocalFileTime(&ft,&lft); |
14 | | } |
15 | | else |
16 | | { |
17 | | // We use these functions instead of FileTimeToLocalFileTime according to |
18 | | // MSDN recommendation: "To account for daylight saving time |
19 | | // when converting a file time to a local time ..." |
20 | | SYSTEMTIME st1,st2; |
21 | | FileTimeToSystemTime(&ft,&st1); |
22 | | SystemTimeToTzSpecificLocalTime(NULL,&st1,&st2); |
23 | | SystemTimeToFileTime(&st2,&lft); |
24 | | |
25 | | // Correct precision loss (low 4 decimal digits) in FileTimeToSystemTime. |
26 | | FILETIME rft; |
27 | | SystemTimeToFileTime(&st1,&rft); |
28 | | uint64 Corrected=INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime)- |
29 | | INT32TO64(rft.dwHighDateTime,rft.dwLowDateTime)+ |
30 | | INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime); |
31 | | lft.dwLowDateTime=(DWORD)Corrected; |
32 | | lft.dwHighDateTime=(DWORD)(Corrected>>32); |
33 | | } |
34 | | |
35 | | SYSTEMTIME st; |
36 | | FileTimeToSystemTime(&lft,&st); |
37 | | lt->Year=st.wYear; |
38 | | lt->Month=st.wMonth; |
39 | | lt->Day=st.wDay; |
40 | | lt->Hour=st.wHour; |
41 | | lt->Minute=st.wMinute; |
42 | | lt->Second=st.wSecond; |
43 | | lt->wDay=st.wDayOfWeek; |
44 | | lt->yDay=lt->Day-1; |
45 | | |
46 | | static int mdays[12]={31,28,31,30,31,30,31,31,30,31,30,31}; |
47 | | for (uint I=1;I<lt->Month && I<=ASIZE(mdays);I++) |
48 | | lt->yDay+=mdays[I-1]; |
49 | | |
50 | | if (lt->Month>2 && IsLeapYear(lt->Year)) |
51 | | lt->yDay++; |
52 | | #else |
53 | 83 | time_t ut=GetUnix(); |
54 | 83 | struct tm *t; |
55 | 83 | t=localtime(&ut); |
56 | | |
57 | 83 | lt->Year=t->tm_year+1900; |
58 | 83 | lt->Month=t->tm_mon+1; |
59 | 83 | lt->Day=t->tm_mday; |
60 | 83 | lt->Hour=t->tm_hour; |
61 | 83 | lt->Minute=t->tm_min; |
62 | 83 | lt->Second=t->tm_sec; |
63 | 83 | lt->wDay=t->tm_wday; |
64 | 83 | lt->yDay=t->tm_yday; |
65 | 83 | #endif |
66 | 83 | lt->Reminder=(itime % TICKS_PER_SECOND); |
67 | 83 | } |
68 | | |
69 | | |
70 | | void RarTime::SetLocal(RarLocalTime *lt) |
71 | 3.78k | { |
72 | | #ifdef _WIN_ALL |
73 | | SYSTEMTIME st; |
74 | | st.wYear=lt->Year; |
75 | | st.wMonth=lt->Month; |
76 | | st.wDay=lt->Day; |
77 | | st.wHour=lt->Hour; |
78 | | st.wMinute=lt->Minute; |
79 | | st.wSecond=lt->Second; |
80 | | st.wMilliseconds=0; |
81 | | st.wDayOfWeek=0; |
82 | | FILETIME lft; |
83 | | if (SystemTimeToFileTime(&st,&lft)) |
84 | | { |
85 | | FILETIME ft; |
86 | | |
87 | | if (WinNT() < WNT_VISTA) |
88 | | { |
89 | | // TzSpecificLocalTimeToSystemTime based code produces 1 hour error on XP. |
90 | | LocalFileTimeToFileTime(&lft,&ft); |
91 | | } |
92 | | else |
93 | | { |
94 | | // Reverse procedure which we do in GetLocal. |
95 | | SYSTEMTIME st1,st2; |
96 | | FileTimeToSystemTime(&lft,&st2); // st2 might be unequal to st, because we added lt->Reminder to lft. |
97 | | TzSpecificLocalTimeToSystemTime(NULL,&st2,&st1); |
98 | | SystemTimeToFileTime(&st1,&ft); |
99 | | |
100 | | // Correct precision loss (low 4 decimal digits) in FileTimeToSystemTime. |
101 | | FILETIME rft; |
102 | | SystemTimeToFileTime(&st2,&rft); |
103 | | uint64 Corrected=INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime)- |
104 | | INT32TO64(rft.dwHighDateTime,rft.dwLowDateTime)+ |
105 | | INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime); |
106 | | ft.dwLowDateTime=(DWORD)Corrected; |
107 | | ft.dwHighDateTime=(DWORD)(Corrected>>32); |
108 | | } |
109 | | |
110 | | SetWinFT(&ft); |
111 | | } |
112 | | else |
113 | | Reset(); |
114 | | #else |
115 | 3.78k | struct tm t; |
116 | | |
117 | 3.78k | t.tm_sec=lt->Second; |
118 | 3.78k | t.tm_min=lt->Minute; |
119 | 3.78k | t.tm_hour=lt->Hour; |
120 | 3.78k | t.tm_mday=lt->Day; |
121 | 3.78k | t.tm_mon=lt->Month-1; |
122 | 3.78k | t.tm_year=lt->Year-1900; |
123 | 3.78k | t.tm_isdst=-1; |
124 | 3.78k | SetUnix(mktime(&t)); |
125 | 3.78k | #endif |
126 | 3.78k | itime+=lt->Reminder; |
127 | 3.78k | } |
128 | | |
129 | | |
130 | | |
131 | | |
132 | | #ifdef _WIN_ALL |
133 | | void RarTime::GetWinFT(FILETIME *ft) |
134 | | { |
135 | | _ULARGE_INTEGER ul; |
136 | | ul.QuadPart=GetWin(); |
137 | | ft->dwLowDateTime=ul.LowPart; |
138 | | ft->dwHighDateTime=ul.HighPart; |
139 | | } |
140 | | |
141 | | |
142 | | void RarTime::SetWinFT(FILETIME *ft) |
143 | | { |
144 | | _ULARGE_INTEGER ul = {ft->dwLowDateTime, ft->dwHighDateTime}; |
145 | | SetWin(ul.QuadPart); |
146 | | } |
147 | | #endif |
148 | | |
149 | | |
150 | | // Get 64-bit representation of Windows FILETIME (100ns since 01.01.1601). |
151 | | uint64 RarTime::GetWin() |
152 | 0 | { |
153 | 0 | return itime/(TICKS_PER_SECOND/10000000); |
154 | 0 | } |
155 | | |
156 | | |
157 | | // Set 64-bit representation of Windows FILETIME (100ns since 01.01.1601). |
158 | | void RarTime::SetWin(uint64 WinTime) |
159 | 0 | { |
160 | 0 | itime=WinTime*(TICKS_PER_SECOND/10000000); |
161 | 0 | } |
162 | | |
163 | | |
164 | | time_t RarTime::GetUnix() |
165 | 834 | { |
166 | 834 | return time_t(GetUnixNS()/1000000000); |
167 | 834 | } |
168 | | |
169 | | |
170 | | void RarTime::SetUnix(time_t ut) |
171 | 8.84k | { |
172 | 8.84k | if (sizeof(ut)>4) |
173 | 8.84k | SetUnixNS(uint64(ut)*1000000000); |
174 | 0 | else |
175 | 0 | { |
176 | | // Convert 32-bit and possibly signed time_t to uint32 first, |
177 | | // uint64 cast is not enough. Otherwise sign can expand to 64 bits. |
178 | 0 | SetUnixNS(uint64(uint32(ut))*1000000000); |
179 | 0 | } |
180 | 8.84k | } |
181 | | |
182 | | |
183 | | // Get the high precision Unix time in nanoseconds since 01-01-1970. |
184 | | uint64 RarTime::GetUnixNS() |
185 | 1.58k | { |
186 | | // 11644473600000000000 - number of ns between 01-01-1601 and 01-01-1970. |
187 | 1.58k | uint64 ushift=INT32TO64(0xA1997B0B,0x4C6A0000); |
188 | 1.58k | return itime*(1000000000/TICKS_PER_SECOND)-ushift; |
189 | 1.58k | } |
190 | | |
191 | | |
192 | | // Set the high precision Unix time in nanoseconds since 01-01-1970. |
193 | | void RarTime::SetUnixNS(uint64 ns) |
194 | 21.1k | { |
195 | | // 11644473600000000000 - number of ns between 01-01-1601 and 01-01-1970. |
196 | 21.1k | uint64 ushift=INT32TO64(0xA1997B0B,0x4C6A0000); |
197 | 21.1k | itime=(ns+ushift)/(1000000000/TICKS_PER_SECOND); |
198 | 21.1k | } |
199 | | |
200 | | |
201 | | uint RarTime::GetDos() |
202 | 0 | { |
203 | 0 | RarLocalTime lt; |
204 | 0 | GetLocal(<); |
205 | 0 | uint DosTime=(lt.Second/2)|(lt.Minute<<5)|(lt.Hour<<11)| |
206 | 0 | (lt.Day<<16)|(lt.Month<<21)|((lt.Year-1980)<<25); |
207 | 0 | return DosTime; |
208 | 0 | } |
209 | | |
210 | | |
211 | | void RarTime::SetDos(uint DosTime) |
212 | 3.70k | { |
213 | 3.70k | RarLocalTime lt; |
214 | 3.70k | lt.Second=(DosTime & 0x1f)*2; |
215 | 3.70k | lt.Minute=(DosTime>>5) & 0x3f; |
216 | 3.70k | lt.Hour=(DosTime>>11) & 0x1f; |
217 | 3.70k | lt.Day=(DosTime>>16) & 0x1f; |
218 | 3.70k | lt.Month=(DosTime>>21) & 0x0f; |
219 | 3.70k | lt.Year=(DosTime>>25)+1980; |
220 | 3.70k | lt.Reminder=0; |
221 | 3.70k | SetLocal(<); |
222 | 3.70k | } |
223 | | |
224 | | |
225 | | void RarTime::GetText(wchar *DateStr,size_t MaxSize,bool FullMS) |
226 | 0 | { |
227 | 0 | if (IsSet()) |
228 | 0 | { |
229 | 0 | RarLocalTime lt; |
230 | 0 | GetLocal(<); |
231 | 0 | if (FullMS) |
232 | 0 | swprintf(DateStr,MaxSize,L"%u-%02u-%02u %02u:%02u:%02u,%09u",lt.Year,lt.Month,lt.Day,lt.Hour,lt.Minute,lt.Second,lt.Reminder*(1000000000/TICKS_PER_SECOND)); |
233 | 0 | else |
234 | 0 | swprintf(DateStr,MaxSize,L"%u-%02u-%02u %02u:%02u",lt.Year,lt.Month,lt.Day,lt.Hour,lt.Minute); |
235 | 0 | } |
236 | 0 | else |
237 | 0 | { |
238 | | // We use escape before '?' to avoid weird C trigraph characters. |
239 | 0 | wcsncpyz(DateStr,L"\?\?\?\?-\?\?-\?\? \?\?:\?\?",MaxSize); |
240 | 0 | } |
241 | 0 | } |
242 | | |
243 | | |
244 | | #ifndef SFX_MODULE |
245 | | void RarTime::SetIsoText(const wchar *TimeText) |
246 | 0 | { |
247 | 0 | int Field[6]; |
248 | 0 | memset(Field,0,sizeof(Field)); |
249 | 0 | for (uint DigitCount=0;*TimeText!=0;TimeText++) |
250 | 0 | if (IsDigit(*TimeText)) |
251 | 0 | { |
252 | 0 | int FieldPos=DigitCount<4 ? 0:(DigitCount-4)/2+1; |
253 | 0 | if (FieldPos<ASIZE(Field)) |
254 | 0 | Field[FieldPos]=Field[FieldPos]*10+*TimeText-'0'; |
255 | 0 | DigitCount++; |
256 | 0 | } |
257 | 0 | RarLocalTime lt; |
258 | 0 | lt.Second=Field[5]; |
259 | 0 | lt.Minute=Field[4]; |
260 | 0 | lt.Hour=Field[3]; |
261 | 0 | lt.Day=Field[2]==0 ? 1:Field[2]; |
262 | 0 | lt.Month=Field[1]==0 ? 1:Field[1]; |
263 | 0 | lt.Year=Field[0]; |
264 | 0 | lt.Reminder=0; |
265 | 0 | SetLocal(<); |
266 | 0 | } |
267 | | #endif |
268 | | |
269 | | |
270 | | #ifndef SFX_MODULE |
271 | | void RarTime::SetAgeText(const wchar *TimeText) |
272 | 0 | { |
273 | 0 | uint Seconds=0,Value=0; |
274 | 0 | for (uint I=0;TimeText[I]!=0;I++) |
275 | 0 | { |
276 | 0 | wchar Ch=TimeText[I]; |
277 | 0 | if (IsDigit(Ch)) |
278 | 0 | Value=Value*10+Ch-'0'; |
279 | 0 | else |
280 | 0 | { |
281 | 0 | switch(etoupperw(Ch)) |
282 | 0 | { |
283 | 0 | case 'D': |
284 | 0 | Seconds+=Value*24*3600; |
285 | 0 | break; |
286 | 0 | case 'H': |
287 | 0 | Seconds+=Value*3600; |
288 | 0 | break; |
289 | 0 | case 'M': |
290 | 0 | Seconds+=Value*60; |
291 | 0 | break; |
292 | 0 | case 'S': |
293 | 0 | Seconds+=Value; |
294 | 0 | break; |
295 | 0 | } |
296 | 0 | Value=0; |
297 | 0 | } |
298 | 0 | } |
299 | 0 | SetCurrentTime(); |
300 | 0 | itime-=uint64(Seconds)*TICKS_PER_SECOND; |
301 | 0 | } |
302 | | #endif |
303 | | |
304 | | |
305 | | void RarTime::SetCurrentTime() |
306 | 4.04k | { |
307 | | #ifdef _WIN_ALL |
308 | | FILETIME ft; |
309 | | SYSTEMTIME st; |
310 | | GetSystemTime(&st); |
311 | | SystemTimeToFileTime(&st,&ft); |
312 | | SetWinFT(&ft); |
313 | | #else |
314 | 4.04k | time_t st; |
315 | 4.04k | time(&st); |
316 | 4.04k | SetUnix(st); |
317 | 4.04k | #endif |
318 | 4.04k | } |
319 | | |
320 | | |
321 | | // Add the specified signed number of nanoseconds. |
322 | | void RarTime::Adjust(int64 ns) |
323 | 3 | { |
324 | 3 | ns/=1000000000/TICKS_PER_SECOND; // Convert ns to internal ticks. |
325 | 3 | itime+=(uint64)ns; |
326 | 3 | } |
327 | | |
328 | | |
329 | | #ifndef SFX_MODULE |
330 | | const wchar *GetMonthName(int Month) |
331 | 0 | { |
332 | 0 | return uiGetMonthName(Month); |
333 | 0 | } |
334 | | #endif |
335 | | |
336 | | |
337 | | bool IsLeapYear(int Year) |
338 | 0 | { |
339 | 0 | return (Year&3)==0 && (Year%100!=0 || Year%400==0); |
340 | 0 | } |