xref: /reactos/dll/win32/kernel32/wine/timezone.c (revision bd2f3d39)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:       See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:         ReactOS system libraries
4c2c66affSColin Finck  * FILE:            dll/win32/kernel32/wine/timezone.c
5c2c66affSColin Finck  * PURPOSE:         Time conversion functions
6c2c66affSColin Finck  * PROGRAMMER:      Ariadne
7c2c66affSColin Finck  *                  DOSDATE and DOSTIME structures from Onno Hovers
8c2c66affSColin Finck  * UPDATE HISTORY:
9c2c66affSColin Finck  *                  Created 19/01/99
10c2c66affSColin Finck  */
11c2c66affSColin Finck 
12c2c66affSColin Finck /* INCLUDES ******************************************************************/
13c2c66affSColin Finck 
14c2c66affSColin Finck #include <k32.h>
15c2c66affSColin Finck 
16c2c66affSColin Finck #define NDEBUG
17c2c66affSColin Finck #include <debug.h>
18c2c66affSColin Finck 
19c2c66affSColin Finck /* TYPES *********************************************************************/
20c2c66affSColin Finck 
21c2c66affSColin Finck #define TICKSPERMIN 600000000
22c2c66affSColin Finck 
23c2c66affSColin Finck #define LL2FILETIME( ll, pft )\
24c2c66affSColin Finck     (pft)->dwLowDateTime = (UINT)(ll); \
25c2c66affSColin Finck     (pft)->dwHighDateTime = (UINT)((ll) >> 32);
26c2c66affSColin Finck #define FILETIME2LL( pft, ll) \
27c2c66affSColin Finck     ll = (((LONGLONG)((pft)->dwHighDateTime))<<32) + (pft)-> dwLowDateTime ;
28c2c66affSColin Finck 
29c2c66affSColin Finck static const int MonthLengths[2][12] =
30c2c66affSColin Finck {
31c2c66affSColin Finck     { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
32c2c66affSColin Finck     { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
33c2c66affSColin Finck };
34c2c66affSColin Finck 
35c2c66affSColin Finck /* STATIC FUNCTIONS **********************************************************/
36c2c66affSColin Finck 
IsLeapYear(int Year)37c2c66affSColin Finck static inline int IsLeapYear(int Year)
38c2c66affSColin Finck {
39c2c66affSColin Finck     return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
40c2c66affSColin Finck }
41c2c66affSColin Finck 
42c2c66affSColin Finck /***********************************************************************
43c2c66affSColin Finck  *  TIME_DayLightCompareDate
44c2c66affSColin Finck  *
45c2c66affSColin Finck  * Compares two dates without looking at the year.
46c2c66affSColin Finck  *
47c2c66affSColin Finck  * PARAMS
48c2c66affSColin Finck  *   date        [in] The local time to compare.
49c2c66affSColin Finck  *   compareDate [in] The daylight savings begin or end date.
50c2c66affSColin Finck  *
51c2c66affSColin Finck  * RETURNS
52c2c66affSColin Finck  *
53c2c66affSColin Finck  *  -1 if date < compareDate
54c2c66affSColin Finck  *   0 if date == compareDate
55c2c66affSColin Finck  *   1 if date > compareDate
56c2c66affSColin Finck  *  -2 if an error occurs
57c2c66affSColin Finck  */
58c2c66affSColin Finck static int
TIME_DayLightCompareDate(const SYSTEMTIME * date,const SYSTEMTIME * compareDate)59c2c66affSColin Finck TIME_DayLightCompareDate(const SYSTEMTIME *date, const SYSTEMTIME *compareDate)
60c2c66affSColin Finck {
61c2c66affSColin Finck     int limit_day, dayinsecs;
62c2c66affSColin Finck 
63c2c66affSColin Finck     if (date->wMonth < compareDate->wMonth)
64c2c66affSColin Finck         return -1; /* We are in a month before the date limit. */
65c2c66affSColin Finck 
66c2c66affSColin Finck     if (date->wMonth > compareDate->wMonth)
67c2c66affSColin Finck         return 1; /* We are in a month after the date limit. */
68c2c66affSColin Finck 
69c2c66affSColin Finck     /* if year is 0 then date is in day-of-week format, otherwise
70c2c66affSColin Finck      * it's absolute date.
71c2c66affSColin Finck      */
72c2c66affSColin Finck     if (compareDate->wYear == 0)
73c2c66affSColin Finck     {
74c2c66affSColin Finck         WORD First;
75c2c66affSColin Finck         /* compareDate->wDay is interpreted as number of the week in the month
76c2c66affSColin Finck          * 5 means: the last week in the month */
77c2c66affSColin Finck         int weekofmonth = compareDate->wDay;
78c2c66affSColin Finck           /* calculate the day of the first DayOfWeek in the month */
79c2c66affSColin Finck         First = ( 6 + compareDate->wDayOfWeek - date->wDayOfWeek + date->wDay
80c2c66affSColin Finck                ) % 7 + 1;
81c2c66affSColin Finck         limit_day = First + 7 * (weekofmonth - 1);
82c2c66affSColin Finck         /* check needed for the 5th weekday of the month */
83c2c66affSColin Finck         if(limit_day > MonthLengths[date->wMonth==2 && IsLeapYear(date->wYear)]
84c2c66affSColin Finck                 [date->wMonth - 1])
85c2c66affSColin Finck             limit_day -= 7;
86c2c66affSColin Finck     }
87c2c66affSColin Finck     else
88c2c66affSColin Finck     {
89c2c66affSColin Finck        limit_day = compareDate->wDay;
90c2c66affSColin Finck     }
91c2c66affSColin Finck 
92c2c66affSColin Finck     /* convert to seconds */
93c2c66affSColin Finck     limit_day = ((limit_day * 24  + compareDate->wHour) * 60 +
94c2c66affSColin Finck             compareDate->wMinute ) * 60;
95c2c66affSColin Finck     dayinsecs = ((date->wDay * 24  + date->wHour) * 60 +
96c2c66affSColin Finck             date->wMinute ) * 60 + date->wSecond;
97c2c66affSColin Finck     /* and compare */
98c2c66affSColin Finck     return dayinsecs < limit_day ? -1 :
99c2c66affSColin Finck            dayinsecs > limit_day ? 1 :
100c2c66affSColin Finck            0;   /* date is equal to the date limit. */
101c2c66affSColin Finck }
102c2c66affSColin Finck 
103c2c66affSColin Finck /***********************************************************************
104c2c66affSColin Finck  *  TIME_CompTimeZoneID
105c2c66affSColin Finck  *
106c2c66affSColin Finck  *  Computes the local time bias for a given time and time zone.
107c2c66affSColin Finck  *
108c2c66affSColin Finck  *  PARAMS
109c2c66affSColin Finck  *      pTZinfo     [in] The time zone data.
110c2c66affSColin Finck  *      lpFileTime  [in] The system or local time.
111c2c66affSColin Finck  *      islocal     [in] it is local time.
112c2c66affSColin Finck  *
113c2c66affSColin Finck  *  RETURNS
114c2c66affSColin Finck  *      TIME_ZONE_ID_INVALID    An error occurred
115c2c66affSColin Finck  *      TIME_ZONE_ID_UNKNOWN    There are no transition time known
116c2c66affSColin Finck  *      TIME_ZONE_ID_STANDARD   Current time is standard time
117c2c66affSColin Finck  *      TIME_ZONE_ID_DAYLIGHT   Current time is daylight savings time
118c2c66affSColin Finck  */
119c2c66affSColin Finck static
120c2c66affSColin Finck DWORD
TIME_CompTimeZoneID(const TIME_ZONE_INFORMATION * pTZinfo,FILETIME * lpFileTime,BOOL islocal)121c2c66affSColin Finck TIME_CompTimeZoneID( const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, BOOL islocal )
122c2c66affSColin Finck {
123c2c66affSColin Finck     int ret, year;
124c2c66affSColin Finck     BOOL beforeStandardDate, afterDaylightDate;
125c2c66affSColin Finck     DWORD retval = TIME_ZONE_ID_INVALID;
126c2c66affSColin Finck     LONGLONG llTime = 0; /* initialized to prevent gcc complaining */
127c2c66affSColin Finck     SYSTEMTIME SysTime;
128c2c66affSColin Finck     FILETIME ftTemp;
129c2c66affSColin Finck 
130c2c66affSColin Finck     if (pTZinfo->DaylightDate.wMonth != 0)
131c2c66affSColin Finck     {
132c2c66affSColin Finck         /* if year is 0 then date is in day-of-week format, otherwise
133c2c66affSColin Finck          * it's absolute date.
134c2c66affSColin Finck          */
135c2c66affSColin Finck         if (pTZinfo->StandardDate.wMonth == 0 ||
136c2c66affSColin Finck             (pTZinfo->StandardDate.wYear == 0 &&
137c2c66affSColin Finck             (pTZinfo->StandardDate.wDay<1 ||
138c2c66affSColin Finck             pTZinfo->StandardDate.wDay>5 ||
139c2c66affSColin Finck             pTZinfo->DaylightDate.wDay<1 ||
140c2c66affSColin Finck             pTZinfo->DaylightDate.wDay>5)))
141c2c66affSColin Finck         {
142c2c66affSColin Finck             SetLastError(ERROR_INVALID_PARAMETER);
143c2c66affSColin Finck             return TIME_ZONE_ID_INVALID;
144c2c66affSColin Finck         }
145c2c66affSColin Finck 
146c2c66affSColin Finck         if (!islocal) {
147c2c66affSColin Finck             FILETIME2LL( lpFileTime, llTime );
148c2c66affSColin Finck             llTime -= pTZinfo->Bias * (LONGLONG)TICKSPERMIN;
149c2c66affSColin Finck             LL2FILETIME( llTime, &ftTemp)
150c2c66affSColin Finck             lpFileTime = &ftTemp;
151c2c66affSColin Finck         }
152c2c66affSColin Finck 
153c2c66affSColin Finck         FileTimeToSystemTime(lpFileTime, &SysTime);
154c2c66affSColin Finck         year = SysTime.wYear;
155c2c66affSColin Finck 
156c2c66affSColin Finck         if (!islocal) {
157c2c66affSColin Finck             llTime -= pTZinfo->DaylightBias * (LONGLONG)TICKSPERMIN;
158c2c66affSColin Finck             LL2FILETIME( llTime, &ftTemp)
159c2c66affSColin Finck             FileTimeToSystemTime(lpFileTime, &SysTime);
160c2c66affSColin Finck         }
161c2c66affSColin Finck 
162c2c66affSColin Finck         /* check for daylight savings */
163c2c66affSColin Finck         if(year == SysTime.wYear) {
164c2c66affSColin Finck             ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->StandardDate);
165c2c66affSColin Finck             if (ret == -2)
166c2c66affSColin Finck                 return TIME_ZONE_ID_INVALID;
167c2c66affSColin Finck 
168c2c66affSColin Finck             beforeStandardDate = ret < 0;
169c2c66affSColin Finck         } else
170c2c66affSColin Finck             beforeStandardDate = SysTime.wYear < year;
171c2c66affSColin Finck 
172c2c66affSColin Finck         if (!islocal) {
173c2c66affSColin Finck             llTime -= ( pTZinfo->StandardBias - pTZinfo->DaylightBias )
174c2c66affSColin Finck                 * (LONGLONG)TICKSPERMIN;
175c2c66affSColin Finck             LL2FILETIME( llTime, &ftTemp)
176c2c66affSColin Finck             FileTimeToSystemTime(lpFileTime, &SysTime);
177c2c66affSColin Finck         }
178c2c66affSColin Finck 
179c2c66affSColin Finck         if(year == SysTime.wYear) {
180c2c66affSColin Finck             ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->DaylightDate);
181c2c66affSColin Finck             if (ret == -2)
182c2c66affSColin Finck                 return TIME_ZONE_ID_INVALID;
183c2c66affSColin Finck 
184c2c66affSColin Finck             afterDaylightDate = ret >= 0;
185c2c66affSColin Finck         } else
186c2c66affSColin Finck             afterDaylightDate = SysTime.wYear > year;
187c2c66affSColin Finck 
188c2c66affSColin Finck         retval = TIME_ZONE_ID_STANDARD;
189c2c66affSColin Finck         if( pTZinfo->DaylightDate.wMonth <  pTZinfo->StandardDate.wMonth ) {
190c2c66affSColin Finck             /* Northern hemisphere */
191c2c66affSColin Finck             if( beforeStandardDate && afterDaylightDate )
192c2c66affSColin Finck                 retval = TIME_ZONE_ID_DAYLIGHT;
193c2c66affSColin Finck         } else    /* Down south */
194c2c66affSColin Finck             if( beforeStandardDate || afterDaylightDate )
195c2c66affSColin Finck             retval = TIME_ZONE_ID_DAYLIGHT;
196c2c66affSColin Finck     } else
197c2c66affSColin Finck         /* No transition date */
198c2c66affSColin Finck         retval = TIME_ZONE_ID_UNKNOWN;
199c2c66affSColin Finck 
200c2c66affSColin Finck     return retval;
201c2c66affSColin Finck }
202c2c66affSColin Finck 
203c2c66affSColin Finck /***********************************************************************
204c2c66affSColin Finck  *  TIME_TimeZoneID
205c2c66affSColin Finck  *
206c2c66affSColin Finck  *  Calculates whether daylight savings is on now.
207c2c66affSColin Finck  *
208c2c66affSColin Finck  *  PARAMS
209c2c66affSColin Finck  *      pTzi [in] Timezone info.
210c2c66affSColin Finck  *
211c2c66affSColin Finck  *  RETURNS
212c2c66affSColin Finck  *      TIME_ZONE_ID_INVALID    An error occurred
213c2c66affSColin Finck  *      TIME_ZONE_ID_UNKNOWN    There are no transition time known
214c2c66affSColin Finck  *      TIME_ZONE_ID_STANDARD   Current time is standard time
215c2c66affSColin Finck  *      TIME_ZONE_ID_DAYLIGHT   Current time is daylight savings time
216c2c66affSColin Finck  */
TIME_ZoneID(const TIME_ZONE_INFORMATION * pTzi)217c2c66affSColin Finck static DWORD TIME_ZoneID( const TIME_ZONE_INFORMATION *pTzi )
218c2c66affSColin Finck {
219c2c66affSColin Finck     FILETIME ftTime;
220c2c66affSColin Finck     GetSystemTimeAsFileTime( &ftTime);
221c2c66affSColin Finck     return TIME_CompTimeZoneID( pTzi, &ftTime, FALSE);
222c2c66affSColin Finck }
223c2c66affSColin Finck 
224c2c66affSColin Finck /***********************************************************************
225c2c66affSColin Finck  *  TIME_GetTimezoneBias
226c2c66affSColin Finck  *
227c2c66affSColin Finck  *  Calculates the local time bias for a given time zone.
228c2c66affSColin Finck  *
229c2c66affSColin Finck  * PARAMS
230c2c66affSColin Finck  *  pTZinfo    [in]  The time zone data.
231c2c66affSColin Finck  *  lpFileTime [in]  The system or local time.
232c2c66affSColin Finck  *  islocal    [in]  It is local time.
233c2c66affSColin Finck  *  pBias      [out] The calculated bias in minutes.
234c2c66affSColin Finck  *
235c2c66affSColin Finck  * RETURNS
236c2c66affSColin Finck  *  TRUE when the time zone bias was calculated.
237c2c66affSColin Finck  */
238c2c66affSColin Finck static BOOL
TIME_GetTimezoneBias(const TIME_ZONE_INFORMATION * pTZinfo,FILETIME * lpFileTime,BOOL islocal,LONG * pBias)239c2c66affSColin Finck TIME_GetTimezoneBias(const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, BOOL islocal, LONG *pBias)
240c2c66affSColin Finck {
241c2c66affSColin Finck     LONG bias = pTZinfo->Bias;
242c2c66affSColin Finck     DWORD tzid = TIME_CompTimeZoneID(pTZinfo, lpFileTime, islocal);
243c2c66affSColin Finck 
244c2c66affSColin Finck     if( tzid == TIME_ZONE_ID_INVALID)
245c2c66affSColin Finck         return FALSE;
246c2c66affSColin Finck     if (tzid == TIME_ZONE_ID_DAYLIGHT)
247c2c66affSColin Finck         bias += pTZinfo->DaylightBias;
248c2c66affSColin Finck     else if (tzid == TIME_ZONE_ID_STANDARD)
249c2c66affSColin Finck         bias += pTZinfo->StandardBias;
250c2c66affSColin Finck     *pBias = bias;
251c2c66affSColin Finck     return TRUE;
252c2c66affSColin Finck }
253c2c66affSColin Finck 
254c2c66affSColin Finck 
255c2c66affSColin Finck /* FUNCTIONS ****************************************************************/
256c2c66affSColin Finck 
257c2c66affSColin Finck /*
258c2c66affSColin Finck  * @implemented
259c2c66affSColin Finck  */
260c2c66affSColin Finck DWORD
261c2c66affSColin Finck WINAPI
GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)262c2c66affSColin Finck GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)
263c2c66affSColin Finck {
26449113829SEric Kohl     RTL_TIME_ZONE_INFORMATION TimeZoneInformation;
265c2c66affSColin Finck     NTSTATUS Status;
266c2c66affSColin Finck 
267c2c66affSColin Finck     DPRINT("GetTimeZoneInformation()\n");
268c2c66affSColin Finck 
269c2c66affSColin Finck     Status = NtQuerySystemInformation(SystemCurrentTimeZoneInformation,
27049113829SEric Kohl                                       &TimeZoneInformation,
27149113829SEric Kohl                                       sizeof(RTL_TIME_ZONE_INFORMATION),
272c2c66affSColin Finck                                       NULL);
273c2c66affSColin Finck     if (!NT_SUCCESS(Status))
274c2c66affSColin Finck     {
275c2c66affSColin Finck         BaseSetLastNTError(Status);
276c2c66affSColin Finck         return TIME_ZONE_ID_INVALID;
277c2c66affSColin Finck     }
278c2c66affSColin Finck 
27949113829SEric Kohl     lpTimeZoneInformation->Bias = TimeZoneInformation.Bias;
28049113829SEric Kohl 
28149113829SEric Kohl     wcsncpy(lpTimeZoneInformation->StandardName,
28249113829SEric Kohl             TimeZoneInformation.StandardName,
28349113829SEric Kohl             ARRAYSIZE(lpTimeZoneInformation->StandardName));
28449113829SEric Kohl     lpTimeZoneInformation->StandardDate.wYear = TimeZoneInformation.StandardDate.Year;
28549113829SEric Kohl     lpTimeZoneInformation->StandardDate.wMonth = TimeZoneInformation.StandardDate.Month;
28649113829SEric Kohl     lpTimeZoneInformation->StandardDate.wDay = TimeZoneInformation.StandardDate.Day;
28749113829SEric Kohl     lpTimeZoneInformation->StandardDate.wHour = TimeZoneInformation.StandardDate.Hour;
28849113829SEric Kohl     lpTimeZoneInformation->StandardDate.wMinute = TimeZoneInformation.StandardDate.Minute;
28949113829SEric Kohl     lpTimeZoneInformation->StandardDate.wSecond = TimeZoneInformation.StandardDate.Second;
290*bd2f3d39SEric Kohl     lpTimeZoneInformation->StandardDate.wMilliseconds = TimeZoneInformation.StandardDate.Milliseconds;
29149113829SEric Kohl     lpTimeZoneInformation->StandardDate.wDayOfWeek = TimeZoneInformation.StandardDate.Weekday;
29249113829SEric Kohl     lpTimeZoneInformation->StandardBias = TimeZoneInformation.StandardBias;
29349113829SEric Kohl 
29449113829SEric Kohl     wcsncpy(lpTimeZoneInformation->DaylightName,
29549113829SEric Kohl             TimeZoneInformation.DaylightName,
29649113829SEric Kohl             ARRAYSIZE(lpTimeZoneInformation->DaylightName));
29749113829SEric Kohl     lpTimeZoneInformation->DaylightDate.wYear = TimeZoneInformation.DaylightDate.Year;
29849113829SEric Kohl     lpTimeZoneInformation->DaylightDate.wMonth = TimeZoneInformation.DaylightDate.Month;
29949113829SEric Kohl     lpTimeZoneInformation->DaylightDate.wDay = TimeZoneInformation.DaylightDate.Day;
30049113829SEric Kohl     lpTimeZoneInformation->DaylightDate.wHour = TimeZoneInformation.DaylightDate.Hour;
30149113829SEric Kohl     lpTimeZoneInformation->DaylightDate.wMinute = TimeZoneInformation.DaylightDate.Minute;
30249113829SEric Kohl     lpTimeZoneInformation->DaylightDate.wSecond = TimeZoneInformation.DaylightDate.Second;
303*bd2f3d39SEric Kohl     lpTimeZoneInformation->DaylightDate.wMilliseconds = TimeZoneInformation.DaylightDate.Milliseconds;
30449113829SEric Kohl     lpTimeZoneInformation->DaylightDate.wDayOfWeek = TimeZoneInformation.DaylightDate.Weekday;
30549113829SEric Kohl     lpTimeZoneInformation->DaylightBias = TimeZoneInformation.DaylightBias;
30649113829SEric Kohl 
307c2c66affSColin Finck     return TIME_ZoneID(lpTimeZoneInformation);
308c2c66affSColin Finck }
309c2c66affSColin Finck 
310c2c66affSColin Finck 
311c2c66affSColin Finck /*
312c2c66affSColin Finck  * @implemented
313c2c66affSColin Finck  */
314c2c66affSColin Finck BOOL
315c2c66affSColin Finck WINAPI
SetTimeZoneInformation(CONST TIME_ZONE_INFORMATION * lpTimeZoneInformation)316c2c66affSColin Finck SetTimeZoneInformation(CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation)
317c2c66affSColin Finck {
31849113829SEric Kohl     RTL_TIME_ZONE_INFORMATION TimeZoneInformation;
319c2c66affSColin Finck     NTSTATUS Status;
320c2c66affSColin Finck 
321c2c66affSColin Finck     DPRINT("SetTimeZoneInformation()\n");
322c2c66affSColin Finck 
32349113829SEric Kohl     TimeZoneInformation.Bias = lpTimeZoneInformation->Bias;
32449113829SEric Kohl 
32549113829SEric Kohl     wcsncpy(TimeZoneInformation.StandardName,
32649113829SEric Kohl             lpTimeZoneInformation->StandardName,
32749113829SEric Kohl             ARRAYSIZE(TimeZoneInformation.StandardName));
32849113829SEric Kohl     TimeZoneInformation.StandardDate.Year = lpTimeZoneInformation->StandardDate.wYear;
32949113829SEric Kohl     TimeZoneInformation.StandardDate.Month = lpTimeZoneInformation->StandardDate.wMonth;
33049113829SEric Kohl     TimeZoneInformation.StandardDate.Day = lpTimeZoneInformation->StandardDate.wDay;
33149113829SEric Kohl     TimeZoneInformation.StandardDate.Hour = lpTimeZoneInformation->StandardDate.wHour;
33249113829SEric Kohl     TimeZoneInformation.StandardDate.Minute = lpTimeZoneInformation->StandardDate.wMinute;
33349113829SEric Kohl     TimeZoneInformation.StandardDate.Second = lpTimeZoneInformation->StandardDate.wSecond;
334*bd2f3d39SEric Kohl     TimeZoneInformation.StandardDate.Milliseconds = lpTimeZoneInformation->StandardDate.wMilliseconds;
33549113829SEric Kohl     TimeZoneInformation.StandardDate.Weekday = lpTimeZoneInformation->StandardDate.wDayOfWeek;
33649113829SEric Kohl     TimeZoneInformation.StandardBias = lpTimeZoneInformation->StandardBias;
33749113829SEric Kohl 
33849113829SEric Kohl     wcsncpy(TimeZoneInformation.DaylightName,
33949113829SEric Kohl             lpTimeZoneInformation->DaylightName,
34049113829SEric Kohl             ARRAYSIZE(TimeZoneInformation.DaylightName));
34149113829SEric Kohl     TimeZoneInformation.DaylightDate.Year = lpTimeZoneInformation->DaylightDate.wYear;
34249113829SEric Kohl     TimeZoneInformation.DaylightDate.Month = lpTimeZoneInformation->DaylightDate.wMonth;
34349113829SEric Kohl     TimeZoneInformation.DaylightDate.Day = lpTimeZoneInformation->DaylightDate.wDay;
34449113829SEric Kohl     TimeZoneInformation.DaylightDate.Hour = lpTimeZoneInformation->DaylightDate.wHour;
34549113829SEric Kohl     TimeZoneInformation.DaylightDate.Minute = lpTimeZoneInformation->DaylightDate.wMinute;
34649113829SEric Kohl     TimeZoneInformation.DaylightDate.Second = lpTimeZoneInformation->DaylightDate.wSecond;
347*bd2f3d39SEric Kohl     TimeZoneInformation.DaylightDate.Milliseconds = lpTimeZoneInformation->DaylightDate.wMilliseconds;
34849113829SEric Kohl     TimeZoneInformation.DaylightDate.Weekday = lpTimeZoneInformation->DaylightDate.wDayOfWeek;
34949113829SEric Kohl     TimeZoneInformation.DaylightBias = lpTimeZoneInformation->DaylightBias;
35049113829SEric Kohl 
35149113829SEric Kohl     Status = RtlSetTimeZoneInformation(&TimeZoneInformation);
352c2c66affSColin Finck     if (!NT_SUCCESS(Status))
353c2c66affSColin Finck     {
354c2c66affSColin Finck         DPRINT1("RtlSetTimeZoneInformation() failed (Status %lx)\n", Status);
355c2c66affSColin Finck         BaseSetLastNTError(Status);
356c2c66affSColin Finck         return FALSE;
357c2c66affSColin Finck     }
358c2c66affSColin Finck 
359c2c66affSColin Finck     Status = NtSetSystemInformation(SystemCurrentTimeZoneInformation,
36049113829SEric Kohl                                     (PVOID)&TimeZoneInformation,
36149113829SEric Kohl                                     sizeof(RTL_TIME_ZONE_INFORMATION));
362c2c66affSColin Finck     if (!NT_SUCCESS(Status))
363c2c66affSColin Finck     {
364c2c66affSColin Finck         DPRINT1("NtSetSystemInformation() failed (Status %lx)\n", Status);
365c2c66affSColin Finck         BaseSetLastNTError(Status);
366c2c66affSColin Finck         return FALSE;
367c2c66affSColin Finck     }
368c2c66affSColin Finck 
369c2c66affSColin Finck     return TRUE;
370c2c66affSColin Finck }
371c2c66affSColin Finck 
372c2c66affSColin Finck /*
373c2c66affSColin Finck  * @implemented
374c2c66affSColin Finck  */
375c2c66affSColin Finck BOOL
376c2c66affSColin Finck WINAPI
SystemTimeToTzSpecificLocalTime(CONST TIME_ZONE_INFORMATION * lpTimeZoneInformation,CONST SYSTEMTIME * lpUniversalTime,LPSYSTEMTIME lpLocalTime)377c2c66affSColin Finck SystemTimeToTzSpecificLocalTime(CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation,
378c2c66affSColin Finck                                 CONST SYSTEMTIME *lpUniversalTime,
379c2c66affSColin Finck                                 LPSYSTEMTIME lpLocalTime)
380c2c66affSColin Finck {
381c2c66affSColin Finck     TIME_ZONE_INFORMATION TzInfo;
382c2c66affSColin Finck     FILETIME FileTime;
383c2c66affSColin Finck     LONGLONG llTime;
384c2c66affSColin Finck     LONG lBias;
385c2c66affSColin Finck 
386c2c66affSColin Finck     if (lpTimeZoneInformation != NULL)
387c2c66affSColin Finck     {
388c2c66affSColin Finck         TzInfo = *lpTimeZoneInformation;
389c2c66affSColin Finck     }
390c2c66affSColin Finck     else
391c2c66affSColin Finck     {
392c2c66affSColin Finck         if (GetTimeZoneInformation(&TzInfo) == TIME_ZONE_ID_INVALID)
393c2c66affSColin Finck             return FALSE;
394c2c66affSColin Finck     }
395c2c66affSColin Finck 
396c2c66affSColin Finck     if (!lpUniversalTime || !lpLocalTime)
397c2c66affSColin Finck         return FALSE;
398c2c66affSColin Finck 
399c2c66affSColin Finck     if (!SystemTimeToFileTime(lpUniversalTime, &FileTime))
400c2c66affSColin Finck         return FALSE;
401c2c66affSColin Finck 
402c2c66affSColin Finck     FILETIME2LL(&FileTime, llTime)
403c2c66affSColin Finck 
404c2c66affSColin Finck     if (!TIME_GetTimezoneBias(&TzInfo, &FileTime, FALSE, &lBias))
405c2c66affSColin Finck         return FALSE;
406c2c66affSColin Finck 
407c2c66affSColin Finck     /* convert minutes to 100-nanoseconds-ticks */
408c2c66affSColin Finck     llTime -= (LONGLONG)lBias * TICKSPERMIN;
409c2c66affSColin Finck 
410c2c66affSColin Finck     LL2FILETIME( llTime, &FileTime)
411c2c66affSColin Finck 
412c2c66affSColin Finck     return FileTimeToSystemTime(&FileTime, lpLocalTime);
413c2c66affSColin Finck }
414c2c66affSColin Finck 
415c2c66affSColin Finck 
416c2c66affSColin Finck /*
417c2c66affSColin Finck  * @implemented (Wine 13 sep 2008)
418c2c66affSColin Finck  */
419c2c66affSColin Finck BOOL
420c2c66affSColin Finck WINAPI
TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION lpTimeZoneInformation,LPSYSTEMTIME lpLocalTime,LPSYSTEMTIME lpUniversalTime)421c2c66affSColin Finck TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION lpTimeZoneInformation,
422c2c66affSColin Finck                                 LPSYSTEMTIME lpLocalTime,
423c2c66affSColin Finck                                 LPSYSTEMTIME lpUniversalTime)
424c2c66affSColin Finck {
425c2c66affSColin Finck     FILETIME ft;
426c2c66affSColin Finck     LONG lBias;
427c2c66affSColin Finck     LONGLONG t;
428c2c66affSColin Finck     TIME_ZONE_INFORMATION tzinfo;
429c2c66affSColin Finck 
430c2c66affSColin Finck     if (lpTimeZoneInformation != NULL)
431c2c66affSColin Finck     {
432c2c66affSColin Finck         tzinfo = *lpTimeZoneInformation;
433c2c66affSColin Finck     }
434c2c66affSColin Finck     else
435c2c66affSColin Finck     {
436c2c66affSColin Finck         if (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_INVALID)
437c2c66affSColin Finck             return FALSE;
438c2c66affSColin Finck     }
439c2c66affSColin Finck 
440c2c66affSColin Finck     if (!SystemTimeToFileTime(lpLocalTime, &ft))
441c2c66affSColin Finck         return FALSE;
442c2c66affSColin Finck     FILETIME2LL( &ft, t)
443c2c66affSColin Finck     if (!TIME_GetTimezoneBias(&tzinfo, &ft, TRUE, &lBias))
444c2c66affSColin Finck         return FALSE;
445c2c66affSColin Finck     /* convert minutes to 100-nanoseconds-ticks */
446c2c66affSColin Finck     t += (LONGLONG)lBias * TICKSPERMIN;
447c2c66affSColin Finck     LL2FILETIME( t, &ft)
448c2c66affSColin Finck     return FileTimeToSystemTime(&ft, lpUniversalTime);
449c2c66affSColin Finck }
450c2c66affSColin Finck 
451c2c66affSColin Finck /* EOF */
452