Implementation of SystemTimeToTzSpecificLocalTime() and TzSpecificLocalTimeToSystemTime()

Martin Fuchs martin-fuchs at gmx.net
Thu Nov 21 17:23:01 CST 2002


ChangeLog
Implementation of SystemTimeToTzSpecificLocalTime() and 
TzSpecificLocalTimeToSystemTime()


Index: dlls/kernel/kernel32.spec
===================================================================
RCS file: /home/wine/wine/dlls/kernel/kernel32.spec,v
retrieving revision 1.74
diff -u -r1.74 kernel32.spec
--- dlls/kernel/kernel32.spec	21 Nov 2002 00:02:10 -0000	1.74
+++ dlls/kernel/kernel32.spec	21 Nov 2002 23:04:46 -0000
@@ -727,6 +727,7 @@
 @ stdcall SuspendThread(long) SuspendThread
 @ stdcall SystemTimeToFileTime(ptr ptr) SystemTimeToFileTime
 @ stdcall SystemTimeToTzSpecificLocalTime (ptr ptr ptr) 
SystemTimeToTzSpecificLocalTime
+@ stdcall TzSpecificLocalTimeToSystemTime (ptr ptr ptr) 
SystemTimeToTzSpecificLocalTime
 @ stdcall TerminateProcess(long long) TerminateProcess
 @ stdcall TerminateThread(long long) TerminateThread
 @ stdcall Thread32First(long ptr) Thread32First
Index: dlls/kernel/time.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/time.c,v
retrieving revision 1.24
diff -u -r1.24 time.c
--- dlls/kernel/time.c	12 Sep 2002 22:07:03 -0000	1.24
+++ dlls/kernel/time.c	21 Nov 2002 23:04:47 -0000
@@ -500,28 +500,282 @@
 
 
 /***********************************************************************
+ *  _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)
+        {
+          long long int 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 + 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 -1;
+
+        beforedaylightsaving = ret < 0;
+
+       _DayLightCompareDate(lpSystemTime, 
&lpTimeZoneInformation->DaylightDate);
+       if (ret == -2)
+          return -1;
+
+        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.@)
  *
  *  Converts the system time (utc) to the local time in the specified time 
zone.
  *
  * RETURNS
  *
- *  Returns true when the local time was calculated.
+ *  Returns TRUE when the local time was calculated.
  *
  */
+
 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. */
 {
-  FIXME(":stub\n");
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return FALSE;
+    FILETIME ft;
+    LONG lBias;
+    long long int 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;
+    long long int 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.@)


-- 
Martin Fuchs
martin-fuchs at gmx.net



More information about the wine-patches mailing list