fixes for _GetTimezoneBias Improved 2
Rein Klazes
rklazes at xs4all.nl
Fri Sep 10 10:33:45 CDT 2004
Hi,
With a fix for calculation on the southern hemisphere. This time without
breaking the north side.
Changelog:
dlls/kernel : time.c
Fixes TzSpecificLocalTimeToSystemTime and
SystemTimeToTzSpecificLocalTime:
- take the time of day into the calculation, so the bias is
calculated correctly during the transition days;
- the transition times are expressed as local time, not system
time;
- correct the daylight logic for use on the southern hemisphere;
- beautify some LONGLONG arithmetic.
Rein.
--
Rein Klazes
rklazes at xs4all.nl
-------------- next part --------------
--- wine/dlls/kernel/time.c 2004-04-28 07:02:57.000000000 +0200
+++ mywine/dlls/kernel/time.c 2004-09-10 15:48:21.000000000 +0200
@@ -53,6 +53,11 @@
#define SETTIME_MAX_ADJUST 120
#define CALINFO_MAX_YEAR 2029
+#define LL2FILETIME( ll, pft )\
+ (pft)->dwLowDateTime = (UINT)(ll); \
+ (pft)->dwHighDateTime = (UINT)((ll) >> 32);
+#define FILETIME2LL( pft, ll) \
+ ll = (((LONGLONG)((pft)->dwHighDateTime))<<32) + (pft)-> dwLowDateTime ;
/***********************************************************************
* SetLocalTime (KERNEL32.@)
@@ -204,19 +209,11 @@
*/
static int _DayLightCompareDate(
- const LPSYSTEMTIME date, /* [in] The date to compare. */
- const LPSYSTEMTIME compareDate) /* [in] The daylight saving begin or end date */
+ const LPSYSTEMTIME date, /* [in] The local time 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. */
- }
+ int limit_day, dayinsecs;
if (date->wMonth < compareDate->wMonth)
return -1; /* We are in a month before the date limit. */
@@ -229,8 +226,8 @@
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 */
+ /* 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 */
@@ -253,19 +250,11 @@
if (weekofmonth == 5)
{
- LONGLONG t, one_day;
-
- t = tmp_ft.dwHighDateTime;
- t <<= 32;
- t += (UINT)tmp_ft.dwLowDateTime;
-
+ LONGLONG t;
+ FILETIME2LL( &tmp_ft, t)
/* subtract one day */
- one_day = 24*60*60;
- one_day *= 10000000;
- t -= one_day;
-
- tmp_ft.dwLowDateTime = (UINT)t;
- tmp_ft.dwHighDateTime = (UINT)(t >> 32);
+ t -= (LONGLONG) 24*60*60*10000000;
+ LL2FILETIME( t, &tmp_ft);
}
if (!FileTimeToSystemTime(&tmp_ft, &tmp))
@@ -295,13 +284,15 @@
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. */
+ /* convert to seconds */
+ limit_day = ((limit_day * 24 + compareDate->wHour) * 60 +
+ compareDate->wMinute ) * 60;
+ dayinsecs = ((date->wDay * 24 + date->wHour) * 60 +
+ date->wMinute ) * 60 + date->wSecond;
+ /* and compare */
+ return dayinsecs < limit_day ? -1 :
+ dayinsecs > limit_day ? 1 :
+ 0; /* date is equal to the date limit. */
}
@@ -316,14 +307,21 @@
*/
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 */
+ const LPTIME_ZONE_INFORMATION
+ lpTimeZoneInformation, /* [in] The time zone data. */
+ LPSYSTEMTIME lpSysOrLocalTime, /* [in] The system or local time. */
+ BOOL islocal, /* [in] it is local time */
+ LONG* pBias /* [out] The calulated bias in minutes */
+ )
{
int ret;
BOOL beforeStandardDate, afterDaylightDate;
BOOL daylightsaving = FALSE;
LONG bias = lpTimeZoneInformation->Bias;
+ FILETIME ft;
+ LONGLONG llTime = 0; /* initialized to prevent gcc complaining */
+ SYSTEMTIME stTemp;
+ LPSYSTEMTIME lpTime = lpSysOrLocalTime;
if (lpTimeZoneInformation->DaylightDate.wMonth != 0)
{
@@ -337,20 +335,43 @@
return FALSE;
}
+ if (!islocal) {
+ if (!SystemTimeToFileTime(lpSysOrLocalTime, &ft)) return -2;
+ FILETIME2LL( &ft, llTime );
+ llTime -= ( lpTimeZoneInformation->Bias +
+ lpTimeZoneInformation->DaylightBias ) * (LONGLONG)600000000;
+ LL2FILETIME( llTime, &ft)
+ FileTimeToSystemTime(&ft, &stTemp);
+ lpTime = &stTemp;
+ }
+
/* check for daylight saving */
- ret = _DayLightCompareDate(lpSystemTime, &lpTimeZoneInformation->StandardDate);
+ ret = _DayLightCompareDate(lpTime, &lpTimeZoneInformation->StandardDate);
if (ret == -2)
return FALSE;
beforeStandardDate = ret < 0;
- ret = _DayLightCompareDate(lpSystemTime, &lpTimeZoneInformation->DaylightDate);
+ if (!islocal) {
+ llTime -= ( lpTimeZoneInformation->StandardBias -
+ lpTimeZoneInformation->DaylightBias ) * (LONGLONG)600000000;
+ LL2FILETIME( llTime, &ft)
+ FileTimeToSystemTime(&ft, &stTemp);
+ lpTime = &stTemp;
+ }
+
+ ret = _DayLightCompareDate(lpTime, &lpTimeZoneInformation->DaylightDate);
if (ret == -2)
return FALSE;
afterDaylightDate = ret >= 0;
- if (beforeStandardDate && afterDaylightDate)
+ if( lpTimeZoneInformation->DaylightDate.wMonth < /* Northern */
+ lpTimeZoneInformation->StandardDate.wMonth ) { /* hemisphere */
+ if( beforeStandardDate && afterDaylightDate )
+ daylightsaving = TRUE;
+ } else /* Down south */
+ if( beforeStandardDate || afterDaylightDate )
daylightsaving = TRUE;
}
@@ -376,13 +397,14 @@
*/
BOOL WINAPI SystemTimeToTzSpecificLocalTime(
- LPTIME_ZONE_INFORMATION lpTimeZoneInformation, /* [in] The desired time zone. */
- LPSYSTEMTIME lpUniversalTime, /* [in] The utc time to base local time on. */
- LPSYSTEMTIME lpLocalTime) /* [out] The local time in the time zone. */
+ LPTIME_ZONE_INFORMATION
+ lpTimeZoneInformation, /* [in] The desired time zone. */
+ LPSYSTEMTIME lpUniversalTime, /* [in] The utc time to base local time on. */
+ LPSYSTEMTIME lpLocalTime) /* [out] The local time in the time zone. */
{
FILETIME ft;
LONG lBias;
- LONGLONG t, bias;
+ LONGLONG llTime;
TIME_ZONE_INFORMATION tzinfo;
if (lpTimeZoneInformation != NULL)
@@ -397,19 +419,12 @@
if (!SystemTimeToFileTime(lpUniversalTime, &ft))
return FALSE;
-
- t = ft.dwHighDateTime;
- t <<= 32;
- t += (UINT)ft.dwLowDateTime;
-
- if (!_GetTimezoneBias(&tzinfo, lpUniversalTime, &lBias))
+ FILETIME2LL( &ft, llTime)
+ if (!_GetTimezoneBias(&tzinfo, lpUniversalTime, FALSE, &lBias))
return FALSE;
-
- bias = (LONGLONG)lBias * 600000000; /* 60 seconds per minute, 100000 [100-nanoseconds-ticks] per second */
- t -= bias;
-
- ft.dwLowDateTime = (UINT)t;
- ft.dwHighDateTime = (UINT)(t >> 32);
+ /* convert minutes to 100-nanoseconds-ticks */
+ llTime -= (LONGLONG)lBias * 600000000;
+ LL2FILETIME( llTime, &ft)
return FileTimeToSystemTime(&ft, lpLocalTime);
}
@@ -431,7 +446,7 @@
{
FILETIME ft;
LONG lBias;
- LONGLONG t, bias;
+ LONGLONG t;
TIME_ZONE_INFORMATION tzinfo;
if (lpTimeZoneInformation != NULL)
@@ -446,20 +461,12 @@
if (!SystemTimeToFileTime(lpLocalTime, &ft))
return FALSE;
-
- t = ft.dwHighDateTime;
- t <<= 32;
- t += (UINT)ft.dwLowDateTime;
-
- if (!_GetTimezoneBias(&tzinfo, lpLocalTime, &lBias))
+ FILETIME2LL( &ft, t)
+ if (!_GetTimezoneBias(&tzinfo, lpLocalTime, TRUE, &lBias))
return FALSE;
-
- bias = (LONGLONG)lBias * 600000000; /* 60 seconds per minute, 100000 [100-nanoseconds-ticks] per second */
- t += bias;
-
- ft.dwLowDateTime = (UINT)t;
- ft.dwHighDateTime = (UINT)(t >> 32);
-
+ /* convert minutes to 100-nanoseconds-ticks */
+ t += (LONGLONG)lBias * 600000000;
+ LL2FILETIME( t, &ft)
return FileTimeToSystemTime(&ft, lpUniversalTime);
}
More information about the wine-patches
mailing list