Implementation of SystemTimeToTzSpecificLocalTime() and
TzSpecificLocalTimeToSystemTime().
This commit is contained in:
parent
7df7cdb6e2
commit
09746293f3
|
@ -819,6 +819,7 @@
|
||||||
@ stub Toolhelp32ReadProcessMemory
|
@ stub Toolhelp32ReadProcessMemory
|
||||||
@ stdcall TransactNamedPipe(long ptr long ptr long ptr ptr) TransactNamedPipe
|
@ stdcall TransactNamedPipe(long ptr long ptr long ptr ptr) TransactNamedPipe
|
||||||
@ stdcall TransmitCommChar(long long) TransmitCommChar
|
@ stdcall TransmitCommChar(long long) TransmitCommChar
|
||||||
|
@ stdcall TzSpecificLocalTimeToSystemTime(ptr ptr ptr) TzSpecificLocalTimeToSystemTime
|
||||||
@ stdcall UTRegister(long str str str ptr ptr ptr) UTRegister
|
@ stdcall UTRegister(long str str str ptr ptr ptr) UTRegister
|
||||||
@ stdcall UTUnRegister(long) UTUnRegister
|
@ stdcall UTUnRegister(long) UTUnRegister
|
||||||
@ stdcall UnMapLS(long) UnMapLS
|
@ stdcall UnMapLS(long) UnMapLS
|
||||||
|
|
|
@ -165,6 +165,181 @@ BOOL WINAPI SetTimeZoneInformation(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* _DayLightCompareDate
|
||||||
|
*
|
||||||
|
* Compares two dates without looking at the year
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
*
|
||||||
|
* -1 if date < compareDate
|
||||||
|
* 0 if date == compareDate
|
||||||
|
* 1 if date > compareDate
|
||||||
|
* -2 if an error occures
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int _DayLightCompareDate(
|
||||||
|
const LPSYSTEMTIME date, /* [in] The date to compare. */
|
||||||
|
const LPSYSTEMTIME compareDate) /* [in] The daylight saving begin or end date */
|
||||||
|
{
|
||||||
|
int limit_day;
|
||||||
|
|
||||||
|
if (compareDate->wYear != 0)
|
||||||
|
{
|
||||||
|
if (date->wMonth < compareDate->wMonth)
|
||||||
|
return -1; /* We are in a year before the date limit. */
|
||||||
|
|
||||||
|
if (date->wMonth > compareDate->wMonth)
|
||||||
|
return 1; /* We are in a year after the date limit. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (date->wMonth < compareDate->wMonth)
|
||||||
|
return -1; /* We are in a month before the date limit. */
|
||||||
|
|
||||||
|
if (date->wMonth > compareDate->wMonth)
|
||||||
|
return 1; /* We are in a month after the date limit. */
|
||||||
|
|
||||||
|
if (compareDate->wDayOfWeek <= 6)
|
||||||
|
{
|
||||||
|
SYSTEMTIME tmp;
|
||||||
|
FILETIME tmp_ft;
|
||||||
|
|
||||||
|
/* compareDate->wDay is interpreted as number of the week in the month. */
|
||||||
|
/* 5 means: the last week in the month */
|
||||||
|
int weekofmonth = compareDate->wDay;
|
||||||
|
|
||||||
|
/* calculate day of week for the first day in the month */
|
||||||
|
memcpy(&tmp, date, sizeof(SYSTEMTIME));
|
||||||
|
tmp.wDay = 1;
|
||||||
|
tmp.wDayOfWeek = -1;
|
||||||
|
|
||||||
|
if (weekofmonth == 5)
|
||||||
|
{
|
||||||
|
/* Go to the beginning of the next month. */
|
||||||
|
if (++tmp.wMonth > 12)
|
||||||
|
{
|
||||||
|
tmp.wMonth = 1;
|
||||||
|
++tmp.wYear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SystemTimeToFileTime(&tmp, &tmp_ft))
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
if (weekofmonth == 5)
|
||||||
|
{
|
||||||
|
LONGLONG t, one_day;
|
||||||
|
|
||||||
|
t = tmp_ft.dwHighDateTime;
|
||||||
|
t <<= 32;
|
||||||
|
t += (UINT)tmp_ft.dwLowDateTime;
|
||||||
|
|
||||||
|
/* substract one day */
|
||||||
|
one_day = 24*60*60;
|
||||||
|
one_day *= 10000000;
|
||||||
|
t -= one_day;
|
||||||
|
|
||||||
|
tmp_ft.dwLowDateTime = (UINT)t;
|
||||||
|
tmp_ft.dwHighDateTime = (UINT)(t >> 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FileTimeToSystemTime(&tmp_ft, &tmp))
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
if (weekofmonth == 5)
|
||||||
|
{
|
||||||
|
/* calculate the last matching day of the week in this month */
|
||||||
|
int dif = tmp.wDayOfWeek - compareDate->wDayOfWeek;
|
||||||
|
if (dif < 0)
|
||||||
|
dif += 7;
|
||||||
|
|
||||||
|
limit_day = tmp.wDay - dif;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* calulcate the matching day of the week in the given week */
|
||||||
|
int dif = compareDate->wDayOfWeek - tmp.wDayOfWeek;
|
||||||
|
if (dif < 0)
|
||||||
|
dif += 7;
|
||||||
|
|
||||||
|
limit_day = tmp.wDay + 7*(weekofmonth-1) + dif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
limit_day = compareDate->wDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (date->wDay < limit_day)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (date->wDay > limit_day)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0; /* date is equal to the date limit. */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* _GetTimezoneBias
|
||||||
|
*
|
||||||
|
* Calculates the local time bias for a given time zone
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
*
|
||||||
|
* Returns TRUE when the time zone bias was calculated.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static BOOL _GetTimezoneBias(
|
||||||
|
const LPTIME_ZONE_INFORMATION lpTimeZoneInformation, /* [in] The time zone data. */
|
||||||
|
LPSYSTEMTIME lpSystemTime, /* [in] The system time. */
|
||||||
|
LONG* pBias) /* [out] The calulated bias in minutes */
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
BOOL beforedaylightsaving, afterdaylightsaving;
|
||||||
|
BOOL daylightsaving = FALSE;
|
||||||
|
LONG bias = lpTimeZoneInformation->Bias;
|
||||||
|
|
||||||
|
if (lpTimeZoneInformation->DaylightDate.wMonth != 0)
|
||||||
|
{
|
||||||
|
if (lpTimeZoneInformation->StandardDate.wMonth == 0 ||
|
||||||
|
lpTimeZoneInformation->StandardDate.wDay<1 ||
|
||||||
|
lpTimeZoneInformation->StandardDate.wDay>5 ||
|
||||||
|
lpTimeZoneInformation->DaylightDate.wDay<1 ||
|
||||||
|
lpTimeZoneInformation->DaylightDate.wDay>5)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for daylight saving */
|
||||||
|
ret = _DayLightCompareDate(lpSystemTime, &lpTimeZoneInformation->StandardDate);
|
||||||
|
if (ret == -2)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
beforedaylightsaving = ret < 0;
|
||||||
|
|
||||||
|
_DayLightCompareDate(lpSystemTime, &lpTimeZoneInformation->DaylightDate);
|
||||||
|
if (ret == -2)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
afterdaylightsaving = ret >= 0;
|
||||||
|
|
||||||
|
if (!beforedaylightsaving && !afterdaylightsaving)
|
||||||
|
daylightsaving = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (daylightsaving)
|
||||||
|
bias += lpTimeZoneInformation->DaylightBias;
|
||||||
|
else if (lpTimeZoneInformation->StandardDate.wMonth != 0)
|
||||||
|
bias += lpTimeZoneInformation->StandardBias;
|
||||||
|
|
||||||
|
*pBias = bias;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* SystemTimeToTzSpecificLocalTime (KERNEL32.@)
|
* SystemTimeToTzSpecificLocalTime (KERNEL32.@)
|
||||||
*
|
*
|
||||||
|
@ -173,22 +348,102 @@ BOOL WINAPI SetTimeZoneInformation(
|
||||||
* RETURNS
|
* RETURNS
|
||||||
*
|
*
|
||||||
* Returns true when the local time was calculated.
|
* Returns true when the local time was calculated.
|
||||||
|
* Returns TRUE when the local time was calculated.
|
||||||
*
|
*
|
||||||
* BUGS
|
|
||||||
*
|
|
||||||
* Does not handle daylight savings time adjustments correctly.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL WINAPI SystemTimeToTzSpecificLocalTime(
|
BOOL WINAPI SystemTimeToTzSpecificLocalTime(
|
||||||
LPTIME_ZONE_INFORMATION lpTimeZoneInformation, /* [in] The desired time zone. */
|
LPTIME_ZONE_INFORMATION lpTimeZoneInformation, /* [in] The desired time zone. */
|
||||||
LPSYSTEMTIME lpUniversalTime, /* [in] The utc time to base local time on. */
|
LPSYSTEMTIME lpUniversalTime, /* [in] The utc time to base local time on. */
|
||||||
LPSYSTEMTIME lpLocalTime) /* [out] The local time in the time zone. */
|
LPSYSTEMTIME lpLocalTime) /* [out] The local time in the time zone. */
|
||||||
{
|
{
|
||||||
FIXME(":stub\n");
|
FILETIME ft;
|
||||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
LONG lBias;
|
||||||
return FALSE;
|
LONGLONG t, bias;
|
||||||
|
TIME_ZONE_INFORMATION tzinfo;
|
||||||
|
|
||||||
|
if (lpTimeZoneInformation != NULL)
|
||||||
|
{
|
||||||
|
memcpy(&tzinfo, lpTimeZoneInformation, sizeof(TIME_ZONE_INFORMATION));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_INVALID)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SystemTimeToFileTime(lpUniversalTime, &ft))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
t = ft.dwHighDateTime;
|
||||||
|
t <<= 32;
|
||||||
|
t += (UINT)ft.dwLowDateTime;
|
||||||
|
|
||||||
|
if (!_GetTimezoneBias(&tzinfo, lpUniversalTime, &lBias))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
bias = lBias * 600000000; /* 60 seconds per minute, 100000 [100-nanoseconds-ticks] per second */
|
||||||
|
t += bias;
|
||||||
|
|
||||||
|
ft.dwLowDateTime = (UINT)t;
|
||||||
|
ft.dwHighDateTime = (UINT)(t >> 32);
|
||||||
|
|
||||||
|
return FileTimeToSystemTime(&ft, lpLocalTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* TzSpecificLocalTimeToSystemTime (KERNEL32.@)
|
||||||
|
*
|
||||||
|
* Converts a local time to a time in Coordinated Universal Time (UTC).
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
*
|
||||||
|
* Returns TRUE when the utc time was calculated.
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOL WINAPI TzSpecificLocalTimeToSystemTime(
|
||||||
|
LPTIME_ZONE_INFORMATION lpTimeZoneInformation, /* [in] The desired time zone. */
|
||||||
|
LPSYSTEMTIME lpLocalTime, /* [in] The local time. */
|
||||||
|
LPSYSTEMTIME lpUniversalTime) /* [out] The calculated utc time. */
|
||||||
|
{
|
||||||
|
FILETIME ft;
|
||||||
|
LONG lBias;
|
||||||
|
LONGLONG t, bias;
|
||||||
|
TIME_ZONE_INFORMATION tzinfo;
|
||||||
|
|
||||||
|
if (lpTimeZoneInformation != NULL)
|
||||||
|
{
|
||||||
|
memcpy(&tzinfo, lpTimeZoneInformation, sizeof(TIME_ZONE_INFORMATION));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_INVALID)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SystemTimeToFileTime(lpLocalTime, &ft))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
t = ft.dwHighDateTime;
|
||||||
|
t <<= 32;
|
||||||
|
t += (UINT)ft.dwLowDateTime;
|
||||||
|
|
||||||
|
if (!_GetTimezoneBias(&tzinfo, lpUniversalTime, &lBias))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
bias = lBias * 600000000; /* 60 seconds per minute, 100000 [100-nanoseconds-ticks] per second */
|
||||||
|
t -= bias;
|
||||||
|
|
||||||
|
ft.dwLowDateTime = (UINT)t;
|
||||||
|
ft.dwHighDateTime = (UINT)(t >> 32);
|
||||||
|
|
||||||
|
return FileTimeToSystemTime(&ft, lpUniversalTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* GetSystemTimeAsFileTime (KERNEL32.@)
|
* GetSystemTimeAsFileTime (KERNEL32.@)
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue