windows-nt/Source/XPSP1/NT/enduser/windows.com/lib/util/timeutil.cpp
2020-09-26 16:20:57 +08:00

248 lines
6.6 KiB
C++

#include <timeutil.h>
////////////////////////////////////////////////////////////////////////////
//
// Helper Function TimeDiff(tm1, tm2)
// helper function to find the difference (in seconds) of 2 system times
//
// Input: 2 SYSTEMTIME structures
// Output: None
// Return: seconds of difference
// > 0 if tm2 is later than tm1
// = 0 if tm2 and tm1 are the same
// < 0 if tm2 is earlier than tm1
//
// On error the function returns 0 even if the two times are not equal
//
// Comment: If the number of seconds goes beyond INT_MAX (that is
// more than 24,855 days, INT_MAX is returned.
// If the number of seconds goes beyond INT_MIN (a negative value,
// means 24,855 days ago), INT_MIN is returned.
//
////////////////////////////////////////////////////////////////////////////
int TimeDiff(SYSTEMTIME tm1, SYSTEMTIME tm2)
{
LONGLONG i64Sec;
int iSec;
//
// convert the two times from SYSTEMTIME format into FILETIME format
//
FILETIME ftm1, ftm2;
if ((SystemTimeToFileTime(&tm1, &ftm1) == 0) ||
(SystemTimeToFileTime(&tm2, &ftm2) == 0))
{
return 0;
}
if ((ftm1.dwHighDateTime == ftm2.dwHighDateTime) &&
(ftm1.dwLowDateTime == ftm2.dwLowDateTime))
{
return 0;
}
//
// convert the two times from FILETIME to LARGE_INTEGER type,
//
LARGE_INTEGER i64Sec1, i64Sec2;
i64Sec2.LowPart = ftm2.dwLowDateTime;
i64Sec2.HighPart = ftm2.dwHighDateTime;
i64Sec1.LowPart = ftm1.dwLowDateTime;
i64Sec1.HighPart = ftm1.dwHighDateTime;
//
// since Windows support LONGLONG, we directly use the quad portion of LARGE_INTEGER
// to get the difference, which is 100 nanoseconds. Then convert the number to seconds.
//
i64Sec = (i64Sec2.QuadPart - i64Sec1.QuadPart) / NanoSec100PerSec;
//
// convert the LONGLONG seconds value into integer, since it shouldn't exceed
// integer limit
//
if (i64Sec > INT_MAX)
{
//
// just in case user is playing with the system time.
// Otherwise, this difference should not go beyond 68 years.
//
iSec = INT_MAX;
}
else
{
if (i64Sec < INT_MIN)
{
iSec = INT_MIN;
}
else
{
iSec = (int)i64Sec;
}
}
return iSec;
}
////////////////////////////////////////////////////////////////////////////
//
// Helper Function TimeAddSeconds(SYSTEMTIME, int, SYSTEMTIME* )
// helper function to calculate time by adding n seconds to
// the given time.
//
// Input: a SYSTEMTIME as base time, an int as seconds to add to the base time
// Output: new time
// Return: HRESULT
//
////////////////////////////////////////////////////////////////////////////
HRESULT TimeAddSeconds(SYSTEMTIME tmBase, int iSeconds, SYSTEMTIME* pTimeNew)
{
// fixcode use i64 calcs
FILETIME ftm;
if (SystemTimeToFileTime(&tmBase, &ftm) == 0)
{
return E_FAIL;
}
LARGE_INTEGER i64Sec;
i64Sec.LowPart = ftm.dwLowDateTime;
i64Sec.HighPart = ftm.dwHighDateTime;
__int64 i64Delay = NanoSec100PerSec;
i64Delay *= iSeconds;
i64Sec.QuadPart += i64Delay;
ftm.dwLowDateTime = i64Sec.LowPart;
ftm.dwHighDateTime = i64Sec.HighPart;
if (FileTimeToSystemTime(&ftm, pTimeNew) == 0)
{
return E_FAIL;
}
return S_OK;
}
//=======================================================================
// String2SystemTime
//=======================================================================
HRESULT String2SystemTime(LPCTSTR pszDateTime, SYSTEMTIME *ptm)
{
// we expect the date/time format as 4-digit year ISO:
// 01234567890123456789
// YYYY.MM.DD HH:MM:SS
//
const TCHAR C_DATE_DEL = _T('.');
const TCHAR C_DATE_TIME_DEL = _T(' ');
const TCHAR C_TIME_DEL = _T(':');
TCHAR szBuf[20];
LPTSTR pszDestEnd;
if (FAILED(StringCchCopyEx(szBuf, ARRAYSIZE(szBuf), pszDateTime, &pszDestEnd, NULL, MISTSAFE_STRING_FLAGS)) ||
19 != pszDestEnd - szBuf)
{
return E_INVALIDARG;
}
for (int i = 0; i < 19; i++)
{
switch (i)
{
case 4:
case 7:
if (szBuf[i] != C_DATE_DEL)
{
return E_INVALIDARG;
}
break;
case 10:
if (szBuf[i] != C_DATE_TIME_DEL)
{
return E_INVALIDARG;
}
break;
case 13:
case 16:
if (szBuf[i] != C_TIME_DEL)
{
return E_INVALIDARG;
}
break;
default:
if (szBuf[i] < _T('0') || pszDateTime[i] > _T('9'))
{
return E_INVALIDARG;
}
break;
}
}
//
// get values
//
szBuf[4] = EOS;
ptm->wYear = (short)_ttoi(szBuf);
szBuf[7] = EOS;
ptm->wMonth = (short)_ttoi(szBuf + 5);
szBuf[10] = EOS;
ptm->wDay = (short)_ttoi(szBuf + 8);
szBuf[13] = EOS;
ptm->wHour = (short)_ttoi(szBuf + 11);
szBuf[16] = EOS;
ptm->wMinute = (short)_ttoi(szBuf + 14);
ptm->wSecond = (short)_ttoi(szBuf + 17);
ptm->wMilliseconds = 0;
//
// validate if this constructed SYSTEMTIME data is good
//
// fixcode should this just be SystemTimeToFileTime() ?
if (GetDateFormat(LOCALE_SYSTEM_DEFAULT,DATE_SHORTDATE, ptm, NULL, NULL, 0) == 0)
{
return E_INVALIDARG;
}
if (GetTimeFormat(LOCALE_SYSTEM_DEFAULT,LOCALE_NOUSEROVERRIDE, ptm, NULL, NULL, 0) == 0)
{
return E_INVALIDARG;
}
return S_OK;
}
//=======================================================================
// SystemTime2String
//=======================================================================
HRESULT SystemTime2String(SYSTEMTIME & tm, LPTSTR pszDateTime, size_t cchSize)
{
if ( pszDateTime == NULL )
{
return E_INVALIDARG;
}
// bug fixed: changed from wsprintf to _snwprintf because an invalid
// date on tm was causing buffer overflow
LPTSTR pszDestEnd;
if (FAILED(StringCchPrintfEx(
pszDateTime,
cchSize,
&pszDestEnd,
NULL,
MISTSAFE_STRING_FLAGS,
TEXT("%4i.%02i.%02i %02i:%02i:%02i"),
tm.wYear,
tm.wMonth,
tm.wDay,
tm.wHour,
tm.wMinute,
tm.wSecond)) ||
pszDestEnd - pszDateTime != 19)
{
return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
}
return S_OK;
}