123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- #include "rar.hpp"
- void RarTime::GetLocal(RarLocalTime *lt)
- {
- #ifdef _WIN_ALL
- FILETIME ft;
- GetWinFT(&ft);
- FILETIME lft;
- if (WinNT() < WNT_VISTA)
- {
- // SystemTimeToTzSpecificLocalTime based code produces 1 hour error on XP.
- FileTimeToLocalFileTime(&ft,&lft);
- }
- else
- {
- // We use these functions instead of FileTimeToLocalFileTime according to
- // MSDN recommendation: "To account for daylight saving time
- // when converting a file time to a local time ..."
- SYSTEMTIME st1,st2;
- FileTimeToSystemTime(&ft,&st1);
- SystemTimeToTzSpecificLocalTime(NULL,&st1,&st2);
- SystemTimeToFileTime(&st2,&lft);
- // Correct precision loss (low 4 decimal digits) in FileTimeToSystemTime.
- FILETIME rft;
- SystemTimeToFileTime(&st1,&rft);
- uint64 Corrected=INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime)-
- INT32TO64(rft.dwHighDateTime,rft.dwLowDateTime)+
- INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime);
- lft.dwLowDateTime=(DWORD)Corrected;
- lft.dwHighDateTime=(DWORD)(Corrected>>32);
- }
- SYSTEMTIME st;
- FileTimeToSystemTime(&lft,&st);
- lt->Year=st.wYear;
- lt->Month=st.wMonth;
- lt->Day=st.wDay;
- lt->Hour=st.wHour;
- lt->Minute=st.wMinute;
- lt->Second=st.wSecond;
- lt->wDay=st.wDayOfWeek;
- lt->yDay=lt->Day-1;
- static int mdays[12]={31,28,31,30,31,30,31,31,30,31,30,31};
- for (uint I=1;I<lt->Month && I<=ASIZE(mdays);I++)
- lt->yDay+=mdays[I-1];
- if (lt->Month>2 && IsLeapYear(lt->Year))
- lt->yDay++;
- #else
- time_t ut=GetUnix();
- struct tm *t;
- t=localtime(&ut);
- lt->Year=t->tm_year+1900;
- lt->Month=t->tm_mon+1;
- lt->Day=t->tm_mday;
- lt->Hour=t->tm_hour;
- lt->Minute=t->tm_min;
- lt->Second=t->tm_sec;
- lt->wDay=t->tm_wday;
- lt->yDay=t->tm_yday;
- #endif
- lt->Reminder=(itime % TICKS_PER_SECOND);
- }
- void RarTime::SetLocal(RarLocalTime *lt)
- {
- #ifdef _WIN_ALL
- SYSTEMTIME st;
- st.wYear=lt->Year;
- st.wMonth=lt->Month;
- st.wDay=lt->Day;
- st.wHour=lt->Hour;
- st.wMinute=lt->Minute;
- st.wSecond=lt->Second;
- st.wMilliseconds=0;
- st.wDayOfWeek=0;
- FILETIME lft;
- if (SystemTimeToFileTime(&st,&lft))
- {
- FILETIME ft;
- if (WinNT() < WNT_VISTA)
- {
- // TzSpecificLocalTimeToSystemTime based code produces 1 hour error on XP.
- LocalFileTimeToFileTime(&lft,&ft);
- }
- else
- {
- // Reverse procedure which we do in GetLocal.
- SYSTEMTIME st1,st2;
- FileTimeToSystemTime(&lft,&st2); // st2 might be unequal to st, because we added lt->Reminder to lft.
- TzSpecificLocalTimeToSystemTime(NULL,&st2,&st1);
- SystemTimeToFileTime(&st1,&ft);
- // Correct precision loss (low 4 decimal digits) in FileTimeToSystemTime.
- FILETIME rft;
- SystemTimeToFileTime(&st2,&rft);
- uint64 Corrected=INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime)-
- INT32TO64(rft.dwHighDateTime,rft.dwLowDateTime)+
- INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime);
- ft.dwLowDateTime=(DWORD)Corrected;
- ft.dwHighDateTime=(DWORD)(Corrected>>32);
- }
- SetWinFT(&ft);
- }
- else
- Reset();
- #else
- struct tm t;
- t.tm_sec=lt->Second;
- t.tm_min=lt->Minute;
- t.tm_hour=lt->Hour;
- t.tm_mday=lt->Day;
- t.tm_mon=lt->Month-1;
- t.tm_year=lt->Year-1900;
- t.tm_isdst=-1;
- SetUnix(mktime(&t));
- #endif
- itime+=lt->Reminder;
- }
- #ifdef _WIN_ALL
- void RarTime::GetWinFT(FILETIME *ft)
- {
- _ULARGE_INTEGER ul;
- ul.QuadPart=GetWin();
- ft->dwLowDateTime=ul.LowPart;
- ft->dwHighDateTime=ul.HighPart;
- }
- void RarTime::SetWinFT(FILETIME *ft)
- {
- _ULARGE_INTEGER ul = {ft->dwLowDateTime, ft->dwHighDateTime};
- SetWin(ul.QuadPart);
- }
- #endif
- // Get 64-bit representation of Windows FILETIME (100ns since 01.01.1601).
- uint64 RarTime::GetWin()
- {
- return itime/(TICKS_PER_SECOND/10000000);
- }
- // Set 64-bit representation of Windows FILETIME (100ns since 01.01.1601).
- void RarTime::SetWin(uint64 WinTime)
- {
- itime=WinTime*(TICKS_PER_SECOND/10000000);
- }
- time_t RarTime::GetUnix()
- {
- return time_t(GetUnixNS()/1000000000);
- }
- void RarTime::SetUnix(time_t ut)
- {
- if (sizeof(ut)>4)
- SetUnixNS(uint64(ut)*1000000000);
- else
- {
- // Convert 32-bit and possibly signed time_t to uint32 first,
- // uint64 cast is not enough. Otherwise sign can expand to 64 bits.
- SetUnixNS(uint64(uint32(ut))*1000000000);
- }
- }
- // Get the high precision Unix time in nanoseconds since 01-01-1970.
- uint64 RarTime::GetUnixNS()
- {
- // 11644473600000000000 - number of ns between 01-01-1601 and 01-01-1970.
- uint64 ushift=INT32TO64(0xA1997B0B,0x4C6A0000);
- return itime*(1000000000/TICKS_PER_SECOND)-ushift;
- }
- // Set the high precision Unix time in nanoseconds since 01-01-1970.
- void RarTime::SetUnixNS(uint64 ns)
- {
- // 11644473600000000000 - number of ns between 01-01-1601 and 01-01-1970.
- uint64 ushift=INT32TO64(0xA1997B0B,0x4C6A0000);
- itime=(ns+ushift)/(1000000000/TICKS_PER_SECOND);
- }
- uint RarTime::GetDos()
- {
- RarLocalTime lt;
- GetLocal(<);
- uint DosTime=(lt.Second/2)|(lt.Minute<<5)|(lt.Hour<<11)|
- (lt.Day<<16)|(lt.Month<<21)|((lt.Year-1980)<<25);
- return DosTime;
- }
- void RarTime::SetDos(uint DosTime)
- {
- RarLocalTime lt;
- lt.Second=(DosTime & 0x1f)*2;
- lt.Minute=(DosTime>>5) & 0x3f;
- lt.Hour=(DosTime>>11) & 0x1f;
- lt.Day=(DosTime>>16) & 0x1f;
- lt.Month=(DosTime>>21) & 0x0f;
- lt.Year=(DosTime>>25)+1980;
- lt.Reminder=0;
- SetLocal(<);
- }
- void RarTime::GetText(wchar *DateStr,size_t MaxSize,bool FullMS)
- {
- if (IsSet())
- {
- RarLocalTime lt;
- GetLocal(<);
- if (FullMS)
- 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));
- else
- swprintf(DateStr,MaxSize,L"%u-%02u-%02u %02u:%02u",lt.Year,lt.Month,lt.Day,lt.Hour,lt.Minute);
- }
- else
- {
- // We use escape before '?' to avoid weird C trigraph characters.
- wcsncpyz(DateStr,L"\?\?\?\?-\?\?-\?\? \?\?:\?\?",MaxSize);
- }
- }
- #ifndef SFX_MODULE
- void RarTime::SetIsoText(const wchar *TimeText)
- {
- int Field[6];
- memset(Field,0,sizeof(Field));
- for (uint DigitCount=0;*TimeText!=0;TimeText++)
- if (IsDigit(*TimeText))
- {
- int FieldPos=DigitCount<4 ? 0:(DigitCount-4)/2+1;
- if (FieldPos<ASIZE(Field))
- Field[FieldPos]=Field[FieldPos]*10+*TimeText-'0';
- DigitCount++;
- }
- RarLocalTime lt;
- lt.Second=Field[5];
- lt.Minute=Field[4];
- lt.Hour=Field[3];
- lt.Day=Field[2]==0 ? 1:Field[2];
- lt.Month=Field[1]==0 ? 1:Field[1];
- lt.Year=Field[0];
- lt.Reminder=0;
- SetLocal(<);
- }
- #endif
- #ifndef SFX_MODULE
- void RarTime::SetAgeText(const wchar *TimeText)
- {
- uint Seconds=0,Value=0;
- for (uint I=0;TimeText[I]!=0;I++)
- {
- wchar Ch=TimeText[I];
- if (IsDigit(Ch))
- Value=Value*10+Ch-'0';
- else
- {
- switch(etoupperw(Ch))
- {
- case 'D':
- Seconds+=Value*24*3600;
- break;
- case 'H':
- Seconds+=Value*3600;
- break;
- case 'M':
- Seconds+=Value*60;
- break;
- case 'S':
- Seconds+=Value;
- break;
- }
- Value=0;
- }
- }
- SetCurrentTime();
- itime-=uint64(Seconds)*TICKS_PER_SECOND;
- }
- #endif
- void RarTime::SetCurrentTime()
- {
- #ifdef _WIN_ALL
- FILETIME ft;
- SYSTEMTIME st;
- GetSystemTime(&st);
- SystemTimeToFileTime(&st,&ft);
- SetWinFT(&ft);
- #else
- time_t st;
- time(&st);
- SetUnix(st);
- #endif
- }
- // Add the specified signed number of nanoseconds.
- void RarTime::Adjust(int64 ns)
- {
- ns/=1000000000/TICKS_PER_SECOND; // Convert ns to internal ticks.
- itime+=(uint64)ns;
- }
- #ifndef SFX_MODULE
- const wchar *GetMonthName(int Month)
- {
- return uiGetMonthName(Month);
- }
- #endif
- bool IsLeapYear(int Year)
- {
- return (Year&3)==0 && (Year%100!=0 || Year%400==0);
- }
|