ReactOS  0.4.13-dev-100-gc8611ae
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 
29 static 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 
37 static 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  */
58 static 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  */
119 static
120 DWORD
121 TIME_CompTimeZoneID( const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, BOOL islocal )
122 {
123  int ret, year;
124  BOOL beforeStandardDate, afterDaylightDate;
125  DWORD retval = TIME_ZONE_ID_INVALID;
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  {
143  return TIME_ZONE_ID_INVALID;
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)
166  return TIME_ZONE_ID_INVALID;
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)
182  return TIME_ZONE_ID_INVALID;
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  */
238 static BOOL
239 TIME_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  */
260 DWORD
261 WINAPI
263 {
264  RTL_TIME_ZONE_INFORMATION TimeZoneInformation;
266 
267  DPRINT("GetTimeZoneInformation()\n");
268 
270  &TimeZoneInformation,
272  NULL);
273  if (!NT_SUCCESS(Status))
274  {
276  return TIME_ZONE_ID_INVALID;
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  */
314 BOOL
315 WINAPI
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,
361  sizeof(RTL_TIME_ZONE_INFORMATION));
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  */
375 BOOL
376 WINAPI
378  CONST SYSTEMTIME *lpUniversalTime,
379  LPSYSTEMTIME lpLocalTime)
380 {
381  TIME_ZONE_INFORMATION TzInfo;
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  */
419 BOOL
420 WINAPI
422  LPSYSTEMTIME lpLocalTime,
423  LPSYSTEMTIME lpUniversalTime)
424 {
425  FILETIME ft;
426  LONG lBias;
427  LONGLONG t;
428  TIME_ZONE_INFORMATION tzinfo;
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 */
static int IsLeapYear(int Year)
Definition: timezone.c:37
static const int MonthLengths[2][12]
Definition: timezone.c:29
USHORT Weekday
Definition: env_spec_w32.h:718
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
static DWORD TIME_ZoneID(const TIME_ZONE_INFORMATION *pTzi)
Definition: timezone.c:217
DWORD WINAPI GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)
Definition: timezone.c:262
VOID WINAPI GetSystemTimeAsFileTime(OUT PFILETIME lpFileTime)
Definition: time.c:128
#define TRUE
Definition: types.h:120
NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
#define TICKSPERMIN
Definition: timezone.c:21
static int compareDate(const void *arg1, const void *arg2)
Definition: entries.cpp:299
WORD wMonth
Definition: winbase.h:871
#define TIME_ZONE_ID_UNKNOWN
Definition: rtltypes.h:250
WORD wDayOfWeek
Definition: winbase.h:872
LONG NTSTATUS
Definition: precomp.h:26
#define TIME_ZONE_ID_INVALID
Definition: winbase.h:283
GLdouble GLdouble t
Definition: gl.h:2047
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
static int TIME_DayLightCompareDate(const SYSTEMTIME *date, const SYSTEMTIME *compareDate)
Definition: timezone.c:59
BOOL WINAPI SystemTimeToTzSpecificLocalTime(CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation, CONST SYSTEMTIME *lpUniversalTime, LPSYSTEMTIME lpLocalTime)
Definition: timezone.c:377
WCHAR First[]
Definition: FormatMessage.c:11
WORD wYear
Definition: winbase.h:870
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
WORD wMinute
Definition: winbase.h:875
GLfloat bias
Definition: glext.h:7909
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
USHORT Milliseconds
Definition: env_spec_w32.h:717
NTSYSAPI NTSTATUS NTAPI NtSetSystemInformation(IN INT SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength)
int64_t LONGLONG
Definition: typedefs.h:66
#define TIME_ZONE_ID_STANDARD
Definition: rtltypes.h:251
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:178
#define LL2FILETIME(ll, pft)
Definition: timezone.c:23
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define FILETIME2LL(pft, ll)
Definition: timezone.c:26
#define WINAPI
Definition: msvc.h:8
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:409
WORD wSecond
Definition: winbase.h:876
WORD wMilliseconds
Definition: winbase.h:877
static DWORD TIME_CompTimeZoneID(const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, BOOL islocal)
Definition: timezone.c:121
int ret
BOOL WINAPI SetTimeZoneInformation(CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation)
Definition: timezone.c:316
SYSTEMTIME StandardDate
Definition: winbase.h:1161
Status
Definition: gdiplustypes.h:24
static BOOL TIME_GetTimezoneBias(const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, BOOL islocal, LONG *pBias)
Definition: timezone.c:239
WORD wDay
Definition: winbase.h:873
BOOL WINAPI SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime, OUT LPFILETIME lpFileTime)
Definition: time.c:148
_CRTIMP wchar_t *__cdecl wcsncpy(wchar_t *_Dest, const wchar_t *_Source, size_t _Count)
WCHAR DaylightName[32]
Definition: winbase.h:1163
__u16 date
Definition: mkdosfs.c:366
WORD wHour
Definition: winbase.h:874
#define DPRINT1
Definition: precomp.h:8
NTSTATUS NTAPI RtlSetTimeZoneInformation(PRTL_TIME_ZONE_INFORMATION TimeZoneInformation)
Definition: timezone.c:88
BOOL WINAPI TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION lpTimeZoneInformation, LPSYSTEMTIME lpLocalTime, LPSYSTEMTIME lpUniversalTime)
Definition: timezone.c:421
#define TIME_ZONE_ID_DAYLIGHT
Definition: rtltypes.h:252
WCHAR StandardName[32]
Definition: winbase.h:1160
#define CONST
Definition: pedump.c:81
SYSTEMTIME DaylightDate
Definition: winbase.h:1164