"Fossies" - the Fresh Open Source Software Archive 
Member "unrar/timefn.cpp" (4 May 2022, 7755 Bytes) of package /linux/misc/unrarsrc-6.1.7.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "timefn.cpp" see the
Fossies "Dox" file reference documentation.
1 #include "rar.hpp"
2
3 void RarTime::GetLocal(RarLocalTime *lt)
4 {
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 time_t ut=GetUnix();
54 struct tm *t;
55 t=localtime(&ut);
56
57 lt->Year=t->tm_year+1900;
58 lt->Month=t->tm_mon+1;
59 lt->Day=t->tm_mday;
60 lt->Hour=t->tm_hour;
61 lt->Minute=t->tm_min;
62 lt->Second=t->tm_sec;
63 lt->wDay=t->tm_wday;
64 lt->yDay=t->tm_yday;
65 #endif
66 lt->Reminder=(itime % TICKS_PER_SECOND);
67 }
68
69
70 void RarTime::SetLocal(RarLocalTime *lt)
71 {
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 struct tm t;
116
117 t.tm_sec=lt->Second;
118 t.tm_min=lt->Minute;
119 t.tm_hour=lt->Hour;
120 t.tm_mday=lt->Day;
121 t.tm_mon=lt->Month-1;
122 t.tm_year=lt->Year-1900;
123 t.tm_isdst=-1;
124 SetUnix(mktime(&t));
125 #endif
126 itime+=lt->Reminder;
127 }
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 {
153 return itime/(TICKS_PER_SECOND/10000000);
154 }
155
156
157 // Set 64-bit representation of Windows FILETIME (100ns since 01.01.1601).
158 void RarTime::SetWin(uint64 WinTime)
159 {
160 itime=WinTime*(TICKS_PER_SECOND/10000000);
161 }
162
163
164 time_t RarTime::GetUnix()
165 {
166 return time_t(GetUnixNS()/1000000000);
167 }
168
169
170 void RarTime::SetUnix(time_t ut)
171 {
172 if (sizeof(ut)>4)
173 SetUnixNS(uint64(ut)*1000000000);
174 else
175 {
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 SetUnixNS(uint64(uint32(ut))*1000000000);
179 }
180 }
181
182
183 // Get the high precision Unix time in nanoseconds since 01-01-1970.
184 uint64 RarTime::GetUnixNS()
185 {
186 // 11644473600000000000 - number of ns between 01-01-1601 and 01-01-1970.
187 uint64 ushift=INT32TO64(0xA1997B0B,0x4C6A0000);
188 return itime*(1000000000/TICKS_PER_SECOND)-ushift;
189 }
190
191
192 // Set the high precision Unix time in nanoseconds since 01-01-1970.
193 void RarTime::SetUnixNS(uint64 ns)
194 {
195 // 11644473600000000000 - number of ns between 01-01-1601 and 01-01-1970.
196 uint64 ushift=INT32TO64(0xA1997B0B,0x4C6A0000);
197 itime=(ns+ushift)/(1000000000/TICKS_PER_SECOND);
198 }
199
200
201 uint RarTime::GetDos()
202 {
203 RarLocalTime lt;
204 GetLocal(<);
205 uint DosTime=(lt.Second/2)|(lt.Minute<<5)|(lt.Hour<<11)|
206 (lt.Day<<16)|(lt.Month<<21)|((lt.Year-1980)<<25);
207 return DosTime;
208 }
209
210
211 void RarTime::SetDos(uint DosTime)
212 {
213 RarLocalTime lt;
214 lt.Second=(DosTime & 0x1f)*2;
215 lt.Minute=(DosTime>>5) & 0x3f;
216 lt.Hour=(DosTime>>11) & 0x1f;
217 lt.Day=(DosTime>>16) & 0x1f;
218 lt.Month=(DosTime>>21) & 0x0f;
219 lt.Year=(DosTime>>25)+1980;
220 lt.Reminder=0;
221 SetLocal(<);
222 }
223
224
225 void RarTime::GetText(wchar *DateStr,size_t MaxSize,bool FullMS)
226 {
227 if (IsSet())
228 {
229 RarLocalTime lt;
230 GetLocal(<);
231 if (FullMS)
232 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 else
234 swprintf(DateStr,MaxSize,L"%u-%02u-%02u %02u:%02u",lt.Year,lt.Month,lt.Day,lt.Hour,lt.Minute);
235 }
236 else
237 {
238 // We use escape before '?' to avoid weird C trigraph characters.
239 wcsncpyz(DateStr,L"\?\?\?\?-\?\?-\?\? \?\?:\?\?",MaxSize);
240 }
241 }
242
243
244 #ifndef SFX_MODULE
245 void RarTime::SetIsoText(const wchar *TimeText)
246 {
247 int Field[6];
248 memset(Field,0,sizeof(Field));
249 for (uint DigitCount=0;*TimeText!=0;TimeText++)
250 if (IsDigit(*TimeText))
251 {
252 int FieldPos=DigitCount<4 ? 0:(DigitCount-4)/2+1;
253 if (FieldPos<ASIZE(Field))
254 Field[FieldPos]=Field[FieldPos]*10+*TimeText-'0';
255 DigitCount++;
256 }
257 RarLocalTime lt;
258 lt.Second=Field[5];
259 lt.Minute=Field[4];
260 lt.Hour=Field[3];
261 lt.Day=Field[2]==0 ? 1:Field[2];
262 lt.Month=Field[1]==0 ? 1:Field[1];
263 lt.Year=Field[0];
264 lt.Reminder=0;
265 SetLocal(<);
266 }
267 #endif
268
269
270 #ifndef SFX_MODULE
271 void RarTime::SetAgeText(const wchar *TimeText)
272 {
273 uint Seconds=0,Value=0;
274 for (uint I=0;TimeText[I]!=0;I++)
275 {
276 wchar Ch=TimeText[I];
277 if (IsDigit(Ch))
278 Value=Value*10+Ch-'0';
279 else
280 {
281 switch(etoupperw(Ch))
282 {
283 case 'D':
284 Seconds+=Value*24*3600;
285 break;
286 case 'H':
287 Seconds+=Value*3600;
288 break;
289 case 'M':
290 Seconds+=Value*60;
291 break;
292 case 'S':
293 Seconds+=Value;
294 break;
295 }
296 Value=0;
297 }
298 }
299 SetCurrentTime();
300 itime-=uint64(Seconds)*TICKS_PER_SECOND;
301 }
302 #endif
303
304
305 void RarTime::SetCurrentTime()
306 {
307 #ifdef _WIN_ALL
308 FILETIME ft;
309 SYSTEMTIME st;
310 GetSystemTime(&st);
311 SystemTimeToFileTime(&st,&ft);
312 SetWinFT(&ft);
313 #else
314 time_t st;
315 time(&st);
316 SetUnix(st);
317 #endif
318 }
319
320
321 // Add the specified signed number of nanoseconds.
322 void RarTime::Adjust(int64 ns)
323 {
324 ns/=1000000000/TICKS_PER_SECOND; // Convert ns to internal ticks.
325 itime+=(uint64)ns;
326 }
327
328
329 #ifndef SFX_MODULE
330 const wchar *GetMonthName(int Month)
331 {
332 return uiGetMonthName(Month);
333 }
334 #endif
335
336
337 bool IsLeapYear(int Year)
338 {
339 return (Year&3)==0 && (Year%100!=0 || Year%400==0);
340 }