1 #include "rar.hpp"
2 #include "string.h"
3 #include <sstream>
4 
5 using namespace std;
6 
RarTime()7 RarTime::RarTime() :
8     rlt()
9 {
10   Reset();
11 }
12 
13 #ifdef _WIN_ALL
operator =(FILETIME & ft)14 RarTime& RarTime::operator =(FILETIME &ft)
15 {
16   FILETIME lft;
17   FileTimeToLocalFileTime(&ft,&lft);
18   SYSTEMTIME st;
19   FileTimeToSystemTime(&lft,&st);
20   rlt.Year=st.wYear;
21   rlt.Month=st.wMonth;
22   rlt.Day=st.wDay;
23   rlt.Hour=st.wHour;
24   rlt.Minute=st.wMinute;
25   rlt.Second=st.wSecond;
26   rlt.wDay=st.wDayOfWeek;
27   rlt.yDay=rlt.Day-1;
28   for (uint I=1;I<rlt.Month;I++)
29   {
30     static const int mdays[12]={31,28,31,30,31,30,31,31,30,31,30,31};
31     rlt.yDay+=mdays[I-1];
32   }
33   if (rlt.Month>2 && IsLeapYear(rlt.Year))
34     rlt.yDay++;
35 
36   st.wMilliseconds=0;
37   FILETIME zft;
38   SystemTimeToFileTime(&st,&zft);
39 
40   // Calculate the time reminder, which is the part of time smaller
41   // than 1 second, represented in 100-nanosecond intervals.
42   rlt.Reminder=INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime)-
43                INT32TO64(zft.dwHighDateTime,zft.dwLowDateTime);
44   return(*this);
45 }
46 
47 
GetWin32(FILETIME * ft)48 void RarTime::GetWin32(FILETIME *ft)
49 {
50   SYSTEMTIME st;
51   st.wYear=rlt.Year;
52   st.wMonth=rlt.Month;
53   st.wDay=rlt.Day;
54   st.wHour=rlt.Hour;
55   st.wMinute=rlt.Minute;
56   st.wSecond=rlt.Second;
57   st.wMilliseconds=0;
58   FILETIME lft;
59   SystemTimeToFileTime(&st,&lft);
60   lft.dwLowDateTime+=rlt.Reminder;
61   if (lft.dwLowDateTime<rlt.Reminder)
62     lft.dwHighDateTime++;
63   LocalFileTimeToFileTime(&lft,ft);
64 }
65 #endif
66 
67 
68 #if defined(_UNIX) || defined(_EMX)
operator =(time_t ut)69 RarTime& RarTime::operator =(time_t ut)
70 {
71   struct tm *t;
72   t=localtime(&ut);
73 
74   rlt.Year=t->tm_year+1900;
75   rlt.Month=t->tm_mon+1;
76   rlt.Day=t->tm_mday;
77   rlt.Hour=t->tm_hour;
78   rlt.Minute=t->tm_min;
79   rlt.Second=t->tm_sec;
80   rlt.Reminder=0;
81   rlt.wDay=t->tm_wday;
82   rlt.yDay=t->tm_yday;
83   return(*this);
84 }
85 
86 
GetUnix()87 time_t RarTime::GetUnix()
88 {
89   struct tm t;
90 
91   t.tm_sec=rlt.Second;
92   t.tm_min=rlt.Minute;
93   t.tm_hour=rlt.Hour;
94   t.tm_mday=rlt.Day;
95   t.tm_mon=rlt.Month-1;
96   t.tm_year=rlt.Year-1900;
97   t.tm_isdst=-1;
98   return(mktime(&t));
99 }
100 #endif
101 
102 // Return the stored time as 64-bit number of 100-nanosecond intervals
103 // since January 1, 1601 for Windows and since January 1, 1970 for Unix.
104 // Actually we do not care since which date this time starts from
105 // as long as this date is the same for GetRaw and SetRaw. We use the value
106 // returned by GetRaw() for time comparisons and for relative operations
107 // like SetRaw(GetRaw()-C).
GetRaw()108 int64 RarTime::GetRaw()
109 {
110   if (!IsSet())
111     return(0);
112 #ifdef _WIN_ALL
113   FILETIME ft;
114   GetWin32(&ft);
115   return(INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime));
116 #elif defined(_UNIX) || defined(_EMX)
117   time_t ut=GetUnix();
118   return(INT32TO64(0,ut)*10000000+rlt.Reminder);
119 #else
120   // We should never be here. It is better to use standard time functions.
121 
122   // Days since 1970. We do not care about leap years for code simplicity.
123   // It should be acceptable for comprisons.
124   int64 r=(rlt.Year-1970)*365; // Days since 1970.
125 
126   // Cumulative day value for beginning of every month.
127   static const int MonthToDay[12]={0,31,60,91,121,152,182,213,244,274,305,335};
128 
129   r+=MonthToDay[rlt.Month-1]+(rlt.Day-1); // Add days since beginning of year.
130   r=r*24+rlt.Hour;   // Hours.
131   r=r*60+rlt.Minute; // Minutes.
132   r=r*60+rlt.Second; // Seconds.
133   r=r*10000000+rlt.Reminder; // 100-nanosecond intervals.
134 
135   return(r);
136 #endif
137 }
138 
139 
140 #ifndef SFX_MODULE
SetRaw(int64 RawTime)141 void RarTime::SetRaw(int64 RawTime)
142 {
143 #ifdef _WIN_ALL
144   FILETIME ft;
145   ft.dwHighDateTime=(DWORD)(RawTime>>32);
146   ft.dwLowDateTime=(DWORD)RawTime;
147   *this=ft;
148 #elif defined(_UNIX) || defined(_EMX)
149   time_t ut=(time_t)(RawTime/10000000);
150   *this=ut;
151   rlt.Reminder=(uint)(RawTime%10000000);
152 #else
153   // We should never be here. It is better to use standard time functions.
154   rlt.Reminder=RawTime%10000000;
155   RawTime/=10000000; // Seconds.
156   rlt.Second=uint(RawTime%60);
157   RawTime/=60;       // Minutes.
158   rlt.Minute=uint(RawTime%60);
159   RawTime/=60;       // Hours.
160   rlt.Hour=uint(RawTime%24);
161   RawTime/=24;       // Days since 1970.
162   rlt.Year=uint(1970+RawTime/365);
163   RawTime%=365;      // Days since beginning of year.
164 
165   // Cumulative day value for beginning of every month.
166   static const int MonthToDay[12]={0,31,60,91,121,152,182,213,244,274,305,335};
167 
168   for (int I=0;I<12;I++)
169     if (RawTime>=MonthToDay[I])
170     {
171       rlt.Day=uint(RawTime-MonthToDay[I]+1);
172       rlt.Month=I+1;
173     }
174 
175   rlt.wDay=0;
176   rlt.yDay=0;
177 #endif
178 }
179 #endif
180 
181 
operator ==(RarTime & rt)182 bool RarTime::operator == (RarTime &rt)
183 {
184   return(rlt.Year==rt.rlt.Year && rlt.Month==rt.rlt.Month &&
185          rlt.Day==rt.rlt.Day && rlt.Hour==rt.rlt.Hour &&
186          rlt.Minute==rt.rlt.Minute && rlt.Second==rt.rlt.Second &&
187          rlt.Reminder==rt.rlt.Reminder);
188 }
189 
190 
operator <(RarTime & rt)191 bool RarTime::operator < (RarTime &rt)
192 {
193   return(GetRaw()<rt.GetRaw());
194 }
195 
196 
operator <=(RarTime & rt)197 bool RarTime::operator <= (RarTime &rt)
198 {
199   return(*this<rt || *this==rt);
200 }
201 
202 
operator >(RarTime & rt)203 bool RarTime::operator > (RarTime &rt)
204 {
205   return(GetRaw()>rt.GetRaw());
206 }
207 
208 
operator >=(RarTime & rt)209 bool RarTime::operator >= (RarTime &rt)
210 {
211   return(*this>rt || *this==rt);
212 }
213 
214 
GetDos()215 uint RarTime::GetDos()
216 {
217   uint DosTime=(rlt.Second/2)|(rlt.Minute<<5)|(rlt.Hour<<11)|
218                (rlt.Day<<16)|(rlt.Month<<21)|((rlt.Year-1980)<<25);
219   return(DosTime);
220 }
221 
222 
SetDos(uint DosTime)223 void RarTime::SetDos(uint DosTime)
224 {
225   rlt.Second=(DosTime & 0x1f)*2;
226   rlt.Minute=(DosTime>>5) & 0x3f;
227   rlt.Hour=(DosTime>>11) & 0x1f;
228   rlt.Day=(DosTime>>16) & 0x1f;
229   rlt.Month=(DosTime>>21) & 0x0f;
230   rlt.Year=(DosTime>>25)+1980;
231   rlt.Reminder=0;
232 }
233 
234 
235 #if !defined(GUI) || !defined(SFX_MODULE)
GetText(char * DateStr,bool FullYear)236 void RarTime::GetText(char *DateStr,bool FullYear)
237 {
238   if (FullYear)
239     sprintf(DateStr,"%02u-%02u-%u %02u:%02u",rlt.Day,rlt.Month,rlt.Year,rlt.Hour,rlt.Minute);
240   else
241     sprintf(DateStr,"%02u-%02u-%02u %02u:%02u",rlt.Day,rlt.Month,rlt.Year%100,rlt.Hour,rlt.Minute);
242 }
243 #endif
244 
245 
GetLocalTimeXML()246 std::string RarTime::GetLocalTimeXML()
247 {
248 	ostringstream oss;
249 	oss << "<Year>" << rlt.Year
250 	<< "</Year>\n<Month>" << rlt.Month
251 	<< "</Month>\n<Day>"  << rlt.Day
252 	<< "</Dayr>\n<Hour>" << rlt.Hour
253 	<< "</Hour>\n<Minute>" << rlt.Minute
254 	<< "</Minuter>\n<Second>" << rlt.Second
255 	<< "</Second>\n<Reminder>" << rlt.Reminder
256 	<< "</Reminder>\n<wDay>" << rlt.wDay
257 	<< "</wDay>\n<yDay>" << rlt.yDay
258 	<< "</yDay>\n";
259 
260 	return oss.str();
261 }
262 
263 #ifndef SFX_MODULE
SetIsoText(const char * TimeText)264 void RarTime::SetIsoText(const char *TimeText)
265 {
266   int Field[6];
267   memset(Field,0,sizeof(Field));
268   for (int DigitCount=0;*TimeText!=0;TimeText++)
269     if (IsDigit(*TimeText))
270     {
271       int FieldPos=DigitCount<4 ? 0:(DigitCount-4)/2+1;
272       if (FieldPos<(int)(sizeof(Field)/sizeof(Field[0])))
273         Field[FieldPos]=Field[FieldPos]*10+*TimeText-'0';
274       DigitCount++;
275     }
276   rlt.Second=Field[5];
277   rlt.Minute=Field[4];
278   rlt.Hour=Field[3];
279   rlt.Day=Field[2]==0 ? 1:Field[2];
280   rlt.Month=Field[1]==0 ? 1:Field[1];
281   rlt.Year=Field[0];
282   rlt.Reminder=0;
283 }
284 #endif
285 
286 
287 #ifndef SFX_MODULE
SetAgeText(const char * TimeText)288 void RarTime::SetAgeText(const char *TimeText)
289 {
290   uint Seconds=0,Value=0;
291   for (int I=0;TimeText[I]!=0;I++)
292   {
293     int Ch=TimeText[I];
294     if (IsDigit(Ch))
295       Value=Value*10+Ch-'0';
296     else
297     {
298       switch(etoupper(Ch))
299       {
300         case 'D':
301           Seconds+=Value*24*3600;
302           break;
303         case 'H':
304           Seconds+=Value*3600;
305           break;
306         case 'M':
307           Seconds+=Value*60;
308           break;
309         case 'S':
310           Seconds+=Value;
311           break;
312       }
313       Value=0;
314     }
315   }
316   SetCurrentTime();
317   int64 RawTime=GetRaw();
318   SetRaw(RawTime-INT32TO64(0,Seconds)*10000000);
319 }
320 #endif
321 
322 
SetCurrentTime()323 void RarTime::SetCurrentTime()
324 {
325 #ifdef _WIN_ALL
326   FILETIME ft;
327   SYSTEMTIME st;
328   GetSystemTime(&st);
329   SystemTimeToFileTime(&st,&ft);
330   *this=ft;
331 #else
332   time_t st;
333   time(&st);
334   *this=st;
335 #endif
336 }
337 
338 
339 #if !defined(SFX_MODULE) && !defined(_WIN_CE)
GetMonthName(int Month)340 const char *GetMonthName(int Month)
341 {
342 #ifdef SILENT
343   return("");
344 #else
345   static const MSGID MonthID[]={
346          MMonthJan,MMonthFeb,MMonthMar,MMonthApr,MMonthMay,MMonthJun,
347          MMonthJul,MMonthAug,MMonthSep,MMonthOct,MMonthNov,MMonthDec
348   };
349   return(St(MonthID[Month]));
350 #endif
351 }
352 #endif
353 
354 
IsLeapYear(int Year)355 bool IsLeapYear(int Year)
356 {
357   return((Year&3)==0 && (Year%100!=0 || Year%400==0));
358 }
359