ReactOS 0.4.16-dev-340-g0540c21
timezone.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/wine/timezone.c
5 * PURPOSE: Time conversion functions
6 * PROGRAMMER: Ariadne
7 * DOSDATE and DOSTIME structures from Onno Hovers
8 * UPDATE HISTORY:
9 * Created 19/01/99
10 */
11
12/* INCLUDES ******************************************************************/
13
14#include <k32.h>
15
16#define NDEBUG
17#include <debug.h>
18
19/* TYPES *********************************************************************/
20
21#define TICKSPERMIN 600000000
22
23#define LL2FILETIME( ll, pft )\
24 (pft)->dwLowDateTime = (UINT)(ll); \
25 (pft)->dwHighDateTime = (UINT)((ll) >> 32);
26#define FILETIME2LL( pft, ll) \
27 ll = (((LONGLONG)((pft)->dwHighDateTime))<<32) + (pft)-> dwLowDateTime ;
28
29static const int MonthLengths[2][12] =
30{
31 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
32 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
33};
34
35/* STATIC FUNCTIONS **********************************************************/
36
37static inline int IsLeapYear(int Year)
38{
39 return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
40}
41
42/***********************************************************************
43 * TIME_DayLightCompareDate
44 *
45 * Compares two dates without looking at the year.
46 *
47 * PARAMS
48 * date [in] The local time to compare.
49 * compareDate [in] The daylight savings begin or end date.
50 *
51 * RETURNS
52 *
53 * -1 if date < compareDate
54 * 0 if date == compareDate
55 * 1 if date > compareDate
56 * -2 if an error occurs
57 */
58static int
60{
61 int limit_day, dayinsecs;
62
63 if (date->wMonth < compareDate->wMonth)
64 return -1; /* We are in a month before the date limit. */
65
66 if (date->wMonth > compareDate->wMonth)
67 return 1; /* We are in a month after the date limit. */
68
69 /* if year is 0 then date is in day-of-week format, otherwise
70 * it's absolute date.
71 */
72 if (compareDate->wYear == 0)
73 {
74 WORD First;
75 /* compareDate->wDay is interpreted as number of the week in the month
76 * 5 means: the last week in the month */
77 int weekofmonth = compareDate->wDay;
78 /* calculate the day of the first DayOfWeek in the month */
79 First = ( 6 + compareDate->wDayOfWeek - date->wDayOfWeek + date->wDay
80 ) % 7 + 1;
81 limit_day = First + 7 * (weekofmonth - 1);
82 /* check needed for the 5th weekday of the month */
83 if(limit_day > MonthLengths[date->wMonth==2 && IsLeapYear(date->wYear)]
84 [date->wMonth - 1])
85 limit_day -= 7;
86 }
87 else
88 {
89 limit_day = compareDate->wDay;
90 }
91
92 /* convert to seconds */
93 limit_day = ((limit_day * 24 + compareDate->wHour) * 60 +
94 compareDate->wMinute ) * 60;
95 dayinsecs = ((date->wDay * 24 + date->wHour) * 60 +
96 date->wMinute ) * 60 + date->wSecond;
97 /* and compare */
98 return dayinsecs < limit_day ? -1 :
99 dayinsecs > limit_day ? 1 :
100 0; /* date is equal to the date limit. */
101}
102
103/***********************************************************************
104 * TIME_CompTimeZoneID
105 *
106 * Computes the local time bias for a given time and time zone.
107 *
108 * PARAMS
109 * pTZinfo [in] The time zone data.
110 * lpFileTime [in] The system or local time.
111 * islocal [in] it is local time.
112 *
113 * RETURNS
114 * TIME_ZONE_ID_INVALID An error occurred
115 * TIME_ZONE_ID_UNKNOWN There are no transition time known
116 * TIME_ZONE_ID_STANDARD Current time is standard time
117 * TIME_ZONE_ID_DAYLIGHT Current time is daylight savings time
118 */
119static
120DWORD
121TIME_CompTimeZoneID( const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, BOOL islocal )
122{
123 int ret, year;
124 BOOL beforeStandardDate, afterDaylightDate;
126 LONGLONG llTime = 0; /* initialized to prevent gcc complaining */
127 SYSTEMTIME SysTime;
128 FILETIME ftTemp;
129
130 if (pTZinfo->DaylightDate.wMonth != 0)
131 {
132 /* if year is 0 then date is in day-of-week format, otherwise
133 * it's absolute date.
134 */
135 if (pTZinfo->StandardDate.wMonth == 0 ||
136 (pTZinfo->StandardDate.wYear == 0 &&
137 (pTZinfo->StandardDate.wDay<1 ||
138 pTZinfo->StandardDate.wDay>5 ||
139 pTZinfo->DaylightDate.wDay<1 ||
140 pTZinfo->DaylightDate.wDay>5)))
141 {
144 }
145
146 if (!islocal) {
147 FILETIME2LL( lpFileTime, llTime );
148 llTime -= pTZinfo->Bias * (LONGLONG)TICKSPERMIN;
149 LL2FILETIME( llTime, &ftTemp)
150 lpFileTime = &ftTemp;
151 }
152
153 FileTimeToSystemTime(lpFileTime, &SysTime);
154 year = SysTime.wYear;
155
156 if (!islocal) {
157 llTime -= pTZinfo->DaylightBias * (LONGLONG)TICKSPERMIN;
158 LL2FILETIME( llTime, &ftTemp)
159 FileTimeToSystemTime(lpFileTime, &SysTime);
160 }
161
162 /* check for daylight savings */
163 if(year == SysTime.wYear) {
164 ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->StandardDate);
165 if (ret == -2)
167
168 beforeStandardDate = ret < 0;
169 } else
170 beforeStandardDate = SysTime.wYear < year;
171
172 if (!islocal) {
173 llTime -= ( pTZinfo->StandardBias - pTZinfo->DaylightBias )
175 LL2FILETIME( llTime, &ftTemp)
176 FileTimeToSystemTime(lpFileTime, &SysTime);
177 }
178
179 if(year == SysTime.wYear) {
180 ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->DaylightDate);
181 if (ret == -2)
183
184 afterDaylightDate = ret >= 0;
185 } else
186 afterDaylightDate = SysTime.wYear > year;
187
188 retval = TIME_ZONE_ID_STANDARD;
189 if( pTZinfo->DaylightDate.wMonth < pTZinfo->StandardDate.wMonth ) {
190 /* Northern hemisphere */
191 if( beforeStandardDate && afterDaylightDate )
192 retval = TIME_ZONE_ID_DAYLIGHT;
193 } else /* Down south */
194 if( beforeStandardDate || afterDaylightDate )
195 retval = TIME_ZONE_ID_DAYLIGHT;
196 } else
197 /* No transition date */
198 retval = TIME_ZONE_ID_UNKNOWN;
199
200 return retval;
201}
202
203/***********************************************************************
204 * TIME_TimeZoneID
205 *
206 * Calculates whether daylight savings is on now.
207 *
208 * PARAMS
209 * pTzi [in] Timezone info.
210 *
211 * RETURNS
212 * TIME_ZONE_ID_INVALID An error occurred
213 * TIME_ZONE_ID_UNKNOWN There are no transition time known
214 * TIME_ZONE_ID_STANDARD Current time is standard time
215 * TIME_ZONE_ID_DAYLIGHT Current time is daylight savings time
216 */
218{
219 FILETIME ftTime;
220 GetSystemTimeAsFileTime( &ftTime);
221 return TIME_CompTimeZoneID( pTzi, &ftTime, FALSE);
222}
223
224/***********************************************************************
225 * TIME_GetTimezoneBias
226 *
227 * Calculates the local time bias for a given time zone.
228 *
229 * PARAMS
230 * pTZinfo [in] The time zone data.
231 * lpFileTime [in] The system or local time.
232 * islocal [in] It is local time.
233 * pBias [out] The calculated bias in minutes.
234 *
235 * RETURNS
236 * TRUE when the time zone bias was calculated.
237 */
238static BOOL
239TIME_GetTimezoneBias(const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, BOOL islocal, LONG *pBias)
240{
241 LONG bias = pTZinfo->Bias;
242 DWORD tzid = TIME_CompTimeZoneID(pTZinfo, lpFileTime, islocal);
243
244 if( tzid == TIME_ZONE_ID_INVALID)
245 return FALSE;
246 if (tzid == TIME_ZONE_ID_DAYLIGHT)
247 bias += pTZinfo->DaylightBias;
248 else if (tzid == TIME_ZONE_ID_STANDARD)
249 bias += pTZinfo->StandardBias;
250 *pBias = bias;
251 return TRUE;
252}
253
254
255/* FUNCTIONS ****************************************************************/
256
257/*
258 * @implemented
259 */
260DWORD
261WINAPI
263{
264 RTL_TIME_ZONE_INFORMATION TimeZoneInformation;
266
267 DPRINT("GetTimeZoneInformation()\n");
268
270 &TimeZoneInformation,
272 NULL);
273 if (!NT_SUCCESS(Status))
274 {
277 }
278
279 lpTimeZoneInformation->Bias = TimeZoneInformation.Bias;
280
281 wcsncpy(lpTimeZoneInformation->StandardName,
282 TimeZoneInformation.StandardName,
283 ARRAYSIZE(lpTimeZoneInformation->StandardName));
284 lpTimeZoneInformation->StandardDate.wYear = TimeZoneInformation.StandardDate.Year;
285 lpTimeZoneInformation->StandardDate.wMonth = TimeZoneInformation.StandardDate.Month;
286 lpTimeZoneInformation->StandardDate.wDay = TimeZoneInformation.StandardDate.Day;
287 lpTimeZoneInformation->StandardDate.wHour = TimeZoneInformation.StandardDate.Hour;
288 lpTimeZoneInformation->StandardDate.wMinute = TimeZoneInformation.StandardDate.Minute;
289 lpTimeZoneInformation->StandardDate.wSecond = TimeZoneInformation.StandardDate.Second;
290 lpTimeZoneInformation->StandardDate.wMilliseconds = TimeZoneInformation.StandardDate.Milliseconds;
291 lpTimeZoneInformation->StandardDate.wDayOfWeek = TimeZoneInformation.StandardDate.Weekday;
292 lpTimeZoneInformation->StandardBias = TimeZoneInformation.StandardBias;
293
294 wcsncpy(lpTimeZoneInformation->DaylightName,
295 TimeZoneInformation.DaylightName,
296 ARRAYSIZE(lpTimeZoneInformation->DaylightName));
297 lpTimeZoneInformation->DaylightDate.wYear = TimeZoneInformation.DaylightDate.Year;
298 lpTimeZoneInformation->DaylightDate.wMonth = TimeZoneInformation.DaylightDate.Month;
299 lpTimeZoneInformation->DaylightDate.wDay = TimeZoneInformation.DaylightDate.Day;
300 lpTimeZoneInformation->DaylightDate.wHour = TimeZoneInformation.DaylightDate.Hour;
301 lpTimeZoneInformation->DaylightDate.wMinute = TimeZoneInformation.DaylightDate.Minute;
302 lpTimeZoneInformation->DaylightDate.wSecond = TimeZoneInformation.DaylightDate.Second;
303 lpTimeZoneInformation->DaylightDate.wMilliseconds = TimeZoneInformation.DaylightDate.Milliseconds;
304 lpTimeZoneInformation->DaylightDate.wDayOfWeek = TimeZoneInformation.DaylightDate.Weekday;
305 lpTimeZoneInformation->DaylightBias = TimeZoneInformation.DaylightBias;
306
307 return TIME_ZoneID(lpTimeZoneInformation);
308}
309
310
311/*
312 * @implemented
313 */
314BOOL
315WINAPI
317{
318 RTL_TIME_ZONE_INFORMATION TimeZoneInformation;
320
321 DPRINT("SetTimeZoneInformation()\n");
322
323 TimeZoneInformation.Bias = lpTimeZoneInformation->Bias;
324
325 wcsncpy(TimeZoneInformation.StandardName,
326 lpTimeZoneInformation->StandardName,
327 ARRAYSIZE(TimeZoneInformation.StandardName));
328 TimeZoneInformation.StandardDate.Year = lpTimeZoneInformation->StandardDate.wYear;
329 TimeZoneInformation.StandardDate.Month = lpTimeZoneInformation->StandardDate.wMonth;
330 TimeZoneInformation.StandardDate.Day = lpTimeZoneInformation->StandardDate.wDay;
331 TimeZoneInformation.StandardDate.Hour = lpTimeZoneInformation->StandardDate.wHour;
332 TimeZoneInformation.StandardDate.Minute = lpTimeZoneInformation->StandardDate.wMinute;
333 TimeZoneInformation.StandardDate.Second = lpTimeZoneInformation->StandardDate.wSecond;
334 TimeZoneInformation.StandardDate.Milliseconds = lpTimeZoneInformation->StandardDate.wMilliseconds;
335 TimeZoneInformation.StandardDate.Weekday = lpTimeZoneInformation->StandardDate.wDayOfWeek;
336 TimeZoneInformation.StandardBias = lpTimeZoneInformation->StandardBias;
337
338 wcsncpy(TimeZoneInformation.DaylightName,
339 lpTimeZoneInformation->DaylightName,
340 ARRAYSIZE(TimeZoneInformation.DaylightName));
341 TimeZoneInformation.DaylightDate.Year = lpTimeZoneInformation->DaylightDate.wYear;
342 TimeZoneInformation.DaylightDate.Month = lpTimeZoneInformation->DaylightDate.wMonth;
343 TimeZoneInformation.DaylightDate.Day = lpTimeZoneInformation->DaylightDate.wDay;
344 TimeZoneInformation.DaylightDate.Hour = lpTimeZoneInformation->DaylightDate.wHour;
345 TimeZoneInformation.DaylightDate.Minute = lpTimeZoneInformation->DaylightDate.wMinute;
346 TimeZoneInformation.DaylightDate.Second = lpTimeZoneInformation->DaylightDate.wSecond;
347 TimeZoneInformation.DaylightDate.Milliseconds = lpTimeZoneInformation->DaylightDate.wMilliseconds;
348 TimeZoneInformation.DaylightDate.Weekday = lpTimeZoneInformation->DaylightDate.wDayOfWeek;
349 TimeZoneInformation.DaylightBias = lpTimeZoneInformation->DaylightBias;
350
351 Status = RtlSetTimeZoneInformation(&TimeZoneInformation);
352 if (!NT_SUCCESS(Status))
353 {
354 DPRINT1("RtlSetTimeZoneInformation() failed (Status %lx)\n", Status);
356 return FALSE;
357 }
358
360 (PVOID)&TimeZoneInformation,
362 if (!NT_SUCCESS(Status))
363 {
364 DPRINT1("NtSetSystemInformation() failed (Status %lx)\n", Status);
366 return FALSE;
367 }
368
369 return TRUE;
370}
371
372/*
373 * @implemented
374 */
375BOOL
376WINAPI
378 CONST SYSTEMTIME *lpUniversalTime,
379 LPSYSTEMTIME lpLocalTime)
380{
382 FILETIME FileTime;
383 LONGLONG llTime;
384 LONG lBias;
385
386 if (lpTimeZoneInformation != NULL)
387 {
388 TzInfo = *lpTimeZoneInformation;
389 }
390 else
391 {
393 return FALSE;
394 }
395
396 if (!lpUniversalTime || !lpLocalTime)
397 return FALSE;
398
399 if (!SystemTimeToFileTime(lpUniversalTime, &FileTime))
400 return FALSE;
401
402 FILETIME2LL(&FileTime, llTime)
403
404 if (!TIME_GetTimezoneBias(&TzInfo, &FileTime, FALSE, &lBias))
405 return FALSE;
406
407 /* convert minutes to 100-nanoseconds-ticks */
408 llTime -= (LONGLONG)lBias * TICKSPERMIN;
409
410 LL2FILETIME( llTime, &FileTime)
411
412 return FileTimeToSystemTime(&FileTime, lpLocalTime);
413}
414
415
416/*
417 * @implemented (Wine 13 sep 2008)
418 */
419BOOL
420WINAPI
422 LPSYSTEMTIME lpLocalTime,
423 LPSYSTEMTIME lpUniversalTime)
424{
425 FILETIME ft;
426 LONG lBias;
427 LONGLONG t;
429
430 if (lpTimeZoneInformation != NULL)
431 {
432 tzinfo = *lpTimeZoneInformation;
433 }
434 else
435 {
437 return FALSE;
438 }
439
440 if (!SystemTimeToFileTime(lpLocalTime, &ft))
441 return FALSE;
442 FILETIME2LL( &ft, t)
443 if (!TIME_GetTimezoneBias(&tzinfo, &ft, TRUE, &lBias))
444 return FALSE;
445 /* convert minutes to 100-nanoseconds-ticks */
446 t += (LONGLONG)lBias * TICKSPERMIN;
447 LL2FILETIME( t, &ft)
448 return FileTimeToSystemTime(&ft, lpUniversalTime);
449}
450
451/* EOF */
NTSYSAPI NTSTATUS NTAPI NtSetSystemInformation(IN INT SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength)
WCHAR First[]
Definition: FormatMessage.c:11
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
VOID WINAPI GetSystemTimeAsFileTime(OUT PFILETIME lpFileTime)
Definition: time.c:128
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
BOOL WINAPI SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime, OUT LPFILETIME lpFileTime)
Definition: time.c:158
static int TIME_DayLightCompareDate(const SYSTEMTIME *date, const SYSTEMTIME *compareDate)
Definition: timezone.c:59
#define TICKSPERMIN
Definition: timezone.c:21
BOOL WINAPI SystemTimeToTzSpecificLocalTime(CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation, CONST SYSTEMTIME *lpUniversalTime, LPSYSTEMTIME lpLocalTime)
Definition: timezone.c:377
#define FILETIME2LL(pft, ll)
Definition: timezone.c:26
static BOOL TIME_GetTimezoneBias(const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, BOOL islocal, LONG *pBias)
Definition: timezone.c:239
#define LL2FILETIME(ll, pft)
Definition: timezone.c:23
BOOL WINAPI SetTimeZoneInformation(CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation)
Definition: timezone.c:316
static DWORD TIME_CompTimeZoneID(const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, BOOL islocal)
Definition: timezone.c:121
static DWORD TIME_ZoneID(const TIME_ZONE_INFORMATION *pTzi)
Definition: timezone.c:217
static const int MonthLengths[2][12]
Definition: timezone.c:29
DWORD WINAPI GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)
Definition: timezone.c:262
BOOL WINAPI TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION lpTimeZoneInformation, LPSYSTEMTIME lpLocalTime, LPSYSTEMTIME lpUniversalTime)
Definition: timezone.c:421
static int compareDate(const void *arg1, const void *arg2)
Definition: entries.cpp:299
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
@ SystemCurrentTimeZoneInformation
Definition: ntddk_ex.h:59
unsigned short WORD
Definition: ntddk_ex.h:93
Status
Definition: gdiplustypes.h:25
GLdouble GLdouble t
Definition: gl.h:2047
GLfloat bias
Definition: glext.h:7909
__u16 date
Definition: mkdosfs.c:8
NTSYSAPI NTSTATUS NTAPI RtlSetTimeZoneInformation(_In_ PRTL_TIME_ZONE_INFORMATION TimeZoneInformation)
#define TIME_ZONE_ID_UNKNOWN
Definition: rtltypes.h:252
#define TIME_ZONE_ID_STANDARD
Definition: rtltypes.h:253
#define TIME_ZONE_ID_DAYLIGHT
Definition: rtltypes.h:254
#define CONST
Definition: pedump.c:81
long LONG
Definition: pedump.c:60
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:167
_CRTIMP wchar_t *__cdecl wcsncpy(wchar_t *_Dest, const wchar_t *_Source, size_t _Count)
#define DPRINT
Definition: sndvol32.h:73
NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
WORD wYear
Definition: winbase.h:930
WORD wMilliseconds
Definition: winbase.h:937
WORD wMonth
Definition: winbase.h:931
WORD wHour
Definition: winbase.h:934
WORD wSecond
Definition: winbase.h:936
WORD wMinute
Definition: winbase.h:935
WORD wDay
Definition: winbase.h:933
WORD wDayOfWeek
Definition: winbase.h:932
USHORT Milliseconds
Definition: env_spec_w32.h:717
USHORT Weekday
Definition: env_spec_w32.h:718
SYSTEMTIME DaylightDate
Definition: winbase.h:1236
WCHAR DaylightName[32]
Definition: winbase.h:1235
WCHAR StandardName[32]
Definition: winbase.h:1232
SYSTEMTIME StandardDate
Definition: winbase.h:1233
int64_t LONGLONG
Definition: typedefs.h:68
#define IsLeapYear(y)
Definition: variant.c:1048
int ret
#define TIME_ZONE_ID_INVALID
Definition: winbase.h:312
#define WINAPI
Definition: msvc.h:6