Fwd: Implementation of SystemTimeToTzSpecificLocalTime() and TzSpecificLocalTimeToSystemTime()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Sorry, did send it to the wrong list.

----------  Forwarded Message  ----------

Subject: Implementation of SystemTimeToTzSpecificLocalTime() and  TzSpecificLocalTimeToSystemTime()
Date: Fri, 13 Dec 2002 21:45:35 +0100
From: Martin Fuchs <martin-fuchs@gmx.net>
To: wine-devel <wine-devel@winehq.com>

Implementation of SystemTimeToTzSpecificLocalTime() and
TzSpecificLocalTimeToSystemTime()

-- 
Martin Fuchs
martin-fuchs@gmx.net
Index: dlls/kernel/kernel32.spec
===================================================================
RCS file: /home/wine/wine/dlls/kernel/kernel32.spec,v
retrieving revision 1.84
diff -u -r1.84 kernel32.spec
--- dlls/kernel/kernel32.spec	12 Dec 2002 03:55:05 -0000	1.84
+++ dlls/kernel/kernel32.spec	13 Dec 2002 20:43:14 -0000
@@ -801,6 +801,7 @@
 @ stdcall SuspendThread(long) SuspendThread
 @ stdcall SystemTimeToFileTime(ptr ptr) SystemTimeToFileTime
 @ stdcall SystemTimeToTzSpecificLocalTime (ptr ptr ptr) SystemTimeToTzSpecificLocalTime
+@ stdcall TzSpecificLocalTimeToSystemTime (ptr ptr ptr) TzSpecificLocalTimeToSystemTime
 @ stub TerminateJobObject
 @ stdcall TerminateProcess(long long) TerminateProcess
 @ stdcall TerminateThread(long long) TerminateThread
Index: dlls/kernel/time.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/time.c,v
retrieving revision 1.27
diff -u -r1.27 time.c
--- dlls/kernel/time.c	13 Dec 2002 20:30:07 -0000	1.27
+++ dlls/kernel/time.c	13 Dec 2002 20:43:15 -0000
@@ -163,6 +163,181 @@
 
 
 /***********************************************************************
+ *  _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-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.@)
  *
  *  Converts the system time (utc) to the local time in the specified time zone.
@@ -170,20 +345,100 @@
  * RETURNS
  *
  *  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(
     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);
 }
+
+
 
 
 /***********************************************************************

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux