Fixed header inclusion order.
[reactos.git] / reactos / lib / kernel32 / misc / time.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/misc/time.c
5 * PURPOSE: Time conversion functions
6 * PROGRAMMER: Boudewijn ( ariadne@xs4all.nl)
7 * DOSDATE and DOSTIME structures from Onno Hovers
8 * UPDATE HISTORY:
9 * Created 19/01/99
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <windows.h>
16 #include <internal/string.h>
17 #include <string.h>
18
19 #define NDEBUG
20 #include <kernel32/kernel32.h>
21
22 /* TYPES *********************************************************************/
23
24 typedef struct __DOSTIME
25 {
26 WORD Second:5;
27 WORD Minute:6;
28 WORD Hour:5;
29 } DOSTIME, *PDOSTIME;
30
31 typedef struct __DOSDATE
32 {
33 WORD Day:5;
34 WORD Month:4;
35 WORD Year:5;
36 } DOSDATE, *PDOSDATE;
37
38 #define TICKSPERMIN 600000000
39 #define TICKSPERSEC 10000000
40 #define TICKSPERMSEC 10000
41 #define SECSPERDAY 86400
42 #define SECSPERHOUR 3600
43 #define SECSPERMIN 60
44 #define MINSPERHOUR 60
45 #define HOURSPERDAY 24
46 #define EPOCHWEEKDAY 0
47 #define DAYSPERWEEK 7
48 #define EPOCHYEAR 1601
49 #define DAYSPERNORMALYEAR 365
50 #define DAYSPERLEAPYEAR 366
51 #define MONSPERYEAR 12
52
53 static const int YearLengths[2] = {DAYSPERNORMALYEAR, DAYSPERLEAPYEAR};
54 static const int MonthLengths[2][MONSPERYEAR] =
55 {
56 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
57 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
58 };
59
60 static __inline int IsLeapYear(int Year)
61 {
62 return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
63 }
64
65 static __inline void NormalizeTimeFields(WORD *FieldToNormalize,
66 WORD *CarryField,
67 int Modulus)
68 {
69 *FieldToNormalize = (WORD) (*FieldToNormalize - Modulus);
70 *CarryField = (WORD) (*CarryField + 1);
71 }
72
73 #define LISECOND RtlEnlargedUnsignedMultiply(SECOND,NSPERSEC)
74 #define LIMINUTE RtlEnlargedUnsignedMultiply(MINUTE,NSPERSEC)
75 #define LIHOUR RtlEnlargedUnsignedMultiply(HOUR,NSPERSEC)
76 #define LIDAY RtlEnlargedUnsignedMultiply(DAY,NSPERSEC)
77 #define LIYEAR RtlEnlargedUnsignedMultiply(YEAR,NSPERSEC)
78 #define LIFOURYEAR RtlEnlargedUnsignedMultiply(FOURYEAR,NSPERSEC)
79 #define LICENTURY RtlEnlargedUnsignedMultiply(CENTURY,NSPERSEC)
80 #define LIMILLENIUM RtlEnlargedUnsignedMultiply(CENTURY,10*NSPERSEC)
81
82
83
84
85 /* FUNCTIONS ****************************************************************/
86
87 WINBOOL
88 STDCALL
89 FileTimeToDosDateTime(
90 CONST FILETIME *lpFileTime,
91 LPWORD lpFatDate,
92 LPWORD lpFatTime
93 )
94 {
95 PDOSTIME pdtime=(PDOSTIME) lpFatTime;
96 PDOSDATE pddate=(PDOSDATE) lpFatDate;
97 SYSTEMTIME SystemTime;
98
99 if ( lpFileTime == NULL )
100 return FALSE;
101
102 if ( lpFatDate == NULL )
103 return FALSE;
104
105 if ( lpFatTime == NULL )
106 return FALSE;
107
108 FileTimeToSystemTime(
109 lpFileTime,
110 &SystemTime
111 );
112
113 pdtime->Second = SystemTime.wSecond;
114 pdtime->Minute = SystemTime.wMinute;
115 pdtime->Hour = SystemTime.wHour;
116
117 pddate->Day = SystemTime.wDay;
118 pddate->Month = SystemTime.wMonth;
119 pddate->Year = SystemTime.wYear - 1980;
120
121 return TRUE;
122 }
123
124 WINBOOL
125 STDCALL
126 DosDateTimeToFileTime(
127 WORD wFatDate,
128 WORD wFatTime,
129 LPFILETIME lpFileTime
130 )
131 {
132 PDOSTIME pdtime = (PDOSTIME) &wFatTime;
133 PDOSDATE pddate = (PDOSDATE) &wFatDate;
134 SYSTEMTIME SystemTime;
135
136 if ( lpFileTime == NULL )
137 return FALSE;
138
139 SystemTime.wMilliseconds = 0;
140 SystemTime.wSecond = pdtime->Second;
141 SystemTime.wMinute = pdtime->Minute;
142 SystemTime.wHour = pdtime->Hour;
143
144 SystemTime.wDay = pddate->Day;
145 SystemTime.wMonth = pddate->Month;
146 SystemTime.wYear = 1980 + pddate->Year;
147
148 SystemTimeToFileTime(&SystemTime,lpFileTime);
149
150 return TRUE;
151 }
152
153 LONG
154 STDCALL
155 CompareFileTime(
156 CONST FILETIME *lpFileTime1,
157 CONST FILETIME *lpFileTime2
158 )
159 {
160 if ( lpFileTime1 == NULL )
161 return 0;
162 if ( lpFileTime2 == NULL )
163 return 0;
164
165 if (*((PLONGLONG)lpFileTime1) > *((PLONGLONG)lpFileTime2))
166 return 1;
167 else if (*((PLONGLONG)lpFileTime1) < *((PLONGLONG)lpFileTime2))
168 return -1;
169
170 return 0;
171 }
172
173 VOID
174 STDCALL
175 GetSystemTimeAsFileTime(PFILETIME lpFileTime)
176 {
177 NtQuerySystemTime ((TIME *)lpFileTime);
178 }
179
180 WINBOOL
181 STDCALL
182 SystemTimeToFileTime(
183 CONST SYSTEMTIME * lpSystemTime,
184 LPFILETIME lpFileTime
185 )
186
187 {
188 int CurYear, CurMonth, MonthLength;
189 long long int rcTime;
190 SYSTEMTIME SystemTime;
191
192 memcpy (&SystemTime, lpSystemTime, sizeof(SYSTEMTIME));
193
194 rcTime = 0;
195
196 /* FIXME: normalize the TIME_FIELDS structure here */
197 while (SystemTime.wSecond >= SECSPERMIN)
198 {
199 NormalizeTimeFields(&SystemTime.wSecond,
200 &SystemTime.wMinute,
201 SECSPERMIN);
202 }
203 while (SystemTime.wMinute >= MINSPERHOUR)
204 {
205 NormalizeTimeFields(&SystemTime.wMinute,
206 &SystemTime.wHour,
207 MINSPERHOUR);
208 }
209 while (SystemTime.wHour >= HOURSPERDAY)
210 {
211 NormalizeTimeFields(&SystemTime.wHour,
212 &SystemTime.wDay,
213 HOURSPERDAY);
214 }
215 MonthLength =
216 MonthLengths[IsLeapYear(SystemTime.wYear)][SystemTime.wMonth - 1];
217 while (SystemTime.wDay > MonthLength)
218 {
219 NormalizeTimeFields(&SystemTime.wDay,
220 &SystemTime.wMonth,
221 MonthLength);
222 }
223 while (SystemTime.wMonth > MONSPERYEAR)
224 {
225 NormalizeTimeFields(&SystemTime.wMonth,
226 &SystemTime.wYear,
227 MONSPERYEAR);
228 }
229
230 /* FIXME: handle calendar corrections here */
231 for (CurYear = EPOCHYEAR; CurYear < SystemTime.wYear; CurYear++)
232 {
233 rcTime += YearLengths[IsLeapYear(CurYear)];
234 }
235 for (CurMonth = 1; CurMonth < SystemTime.wMonth; CurMonth++)
236 {
237 rcTime += MonthLengths[IsLeapYear(CurYear)][CurMonth - 1];
238 }
239 rcTime += SystemTime.wDay - 1;
240 rcTime *= SECSPERDAY;
241 rcTime += SystemTime.wHour * SECSPERHOUR +
242 SystemTime.wMinute * SECSPERMIN + SystemTime.wSecond;
243 rcTime *= TICKSPERSEC;
244 rcTime += SystemTime.wMilliseconds * TICKSPERMSEC;
245
246 *lpFileTime = *(FILETIME *)&rcTime;
247
248 return TRUE;
249 }
250
251 // dwDayOfWeek = RtlLargeIntegerDivide(FileTime,LIDAY,&dwRemDay);
252 // lpSystemTime->wDayOfWeek = 1 + GET_LARGE_INTEGER_LOW_PART(dwDayOfWeek) % 7;
253
254
255
256 WINBOOL
257 STDCALL
258 FileTimeToSystemTime(
259 CONST FILETIME *lpFileTime,
260 LPSYSTEMTIME lpSystemTime
261 )
262 {
263 const int *Months;
264 int LeapSecondCorrections, SecondsInDay, CurYear;
265 int LeapYear, CurMonth;
266 long int Days;
267 long long int Time = *((long long int*)lpFileTime);
268
269 /* Extract millisecond from time and convert time into seconds */
270 lpSystemTime->wMilliseconds = (WORD)((Time % TICKSPERSEC) / TICKSPERMSEC);
271 Time = Time / TICKSPERSEC;
272
273 /* FIXME: Compute the number of leap second corrections here */
274 LeapSecondCorrections = 0;
275
276 /* Split the time into days and seconds within the day */
277 Days = Time / SECSPERDAY;
278 SecondsInDay = Time % SECSPERDAY;
279
280 /* Adjust the values for GMT and leap seconds */
281 SecondsInDay += LeapSecondCorrections;
282 while (SecondsInDay < 0)
283 {
284 SecondsInDay += SECSPERDAY;
285 Days--;
286 }
287 while (SecondsInDay >= SECSPERDAY)
288 {
289 SecondsInDay -= SECSPERDAY;
290 Days++;
291 }
292
293 /* compute time of day */
294 lpSystemTime->wHour = (WORD) (SecondsInDay / SECSPERHOUR);
295 SecondsInDay = SecondsInDay % SECSPERHOUR;
296 lpSystemTime->wMinute = (WORD) (SecondsInDay / SECSPERMIN);
297 lpSystemTime->wSecond = (WORD) (SecondsInDay % SECSPERMIN);
298
299 /* FIXME: handle the possibility that we are on a leap second (i.e. Second = 60) */
300
301 /* compute day of week */
302 lpSystemTime->wDayOfWeek = (WORD) ((EPOCHWEEKDAY + Days) % DAYSPERWEEK);
303
304 /* compute year */
305 CurYear = EPOCHYEAR;
306 /* FIXME: handle calendar modifications */
307 while (1)
308 {
309 LeapYear = IsLeapYear(CurYear);
310 if (Days < (long) YearLengths[LeapYear])
311 {
312 break;
313 }
314 CurYear++;
315 Days = Days - (long) YearLengths[LeapYear];
316 }
317 lpSystemTime->wYear = (WORD) CurYear;
318
319 /* Compute month of year */
320 Months = MonthLengths[LeapYear];
321 for (CurMonth = 0; Days >= (long) Months[CurMonth]; CurMonth++)
322 Days = Days - (long) Months[CurMonth];
323 lpSystemTime->wMonth = (WORD) (CurMonth + 1);
324 lpSystemTime->wDay = (WORD) (Days + 1);
325
326 return TRUE;
327 }
328
329
330 WINBOOL
331 STDCALL
332 FileTimeToLocalFileTime(
333 CONST FILETIME *lpFileTime,
334 LPFILETIME lpLocalFileTime
335 )
336 {
337 // FIXME: include time bias
338 *((PLONGLONG)lpLocalFileTime) = *((PLONGLONG)lpFileTime);
339
340 return TRUE;
341 }
342
343 WINBOOL
344 STDCALL
345 LocalFileTimeToFileTime(
346 CONST FILETIME *lpLocalFileTime,
347 LPFILETIME lpFileTime
348 )
349 {
350 // FIXME: include time bias
351 *((PLONGLONG)lpFileTime) = *((PLONGLONG)lpLocalFileTime);
352
353 return TRUE;
354 }
355
356 VOID
357 STDCALL
358 GetLocalTime(
359 LPSYSTEMTIME lpSystemTime
360 )
361 {
362 FILETIME FileTime;
363 FILETIME LocalFileTime;
364
365 NtQuerySystemTime ((TIME*)&FileTime);
366 FileTimeToLocalFileTime (&FileTime, &LocalFileTime);
367 FileTimeToSystemTime (&LocalFileTime, lpSystemTime);
368 }
369
370 VOID
371 STDCALL
372 GetSystemTime(
373 LPSYSTEMTIME lpSystemTime
374 )
375 {
376 FILETIME FileTime;
377
378 NtQuerySystemTime ((TIME*)&FileTime);
379 FileTimeToSystemTime (&FileTime, lpSystemTime);
380 }
381
382 WINBOOL
383 STDCALL
384 SetLocalTime(
385 CONST SYSTEMTIME *lpSystemTime
386 )
387 {
388 FILETIME LocalFileTime;
389 LARGE_INTEGER FileTime;
390 NTSTATUS errCode;
391
392 SystemTimeToFileTime (lpSystemTime, &LocalFileTime);
393 LocalFileTimeToFileTime (&LocalFileTime, (FILETIME *)&FileTime);
394 errCode = NtSetSystemTime (&FileTime, &FileTime);
395 if (!NT_SUCCESS(errCode))
396 return FALSE;
397 return TRUE;
398 }
399
400 WINBOOL
401 STDCALL
402 SetSystemTime(
403 CONST SYSTEMTIME *lpSystemTime
404 )
405 {
406 LARGE_INTEGER NewSystemTime;
407 NTSTATUS errCode;
408
409 SystemTimeToFileTime (lpSystemTime, (PFILETIME)&NewSystemTime);
410 errCode = NtSetSystemTime (&NewSystemTime, &NewSystemTime);
411 if (!NT_SUCCESS(errCode))
412 return FALSE;
413 return TRUE;
414 }
415
416 /*
417 typedef struct _TIME_ZONE_INFORMATION { // tzi
418 LONG Bias;
419 WCHAR StandardName[ 32 ];
420 SYSTEMTIME StandardDate;
421 LONG StandardBias;
422 WCHAR DaylightName[ 32 ];
423 SYSTEMTIME DaylightDate;
424 LONG DaylightBias;
425 } TIME_ZONE_INFORMATION;
426 TIME_ZONE_INFORMATION TimeZoneInformation = {60,"CET",;
427
428 */
429 DWORD
430 STDCALL
431 GetTimeZoneInformation(
432 LPTIME_ZONE_INFORMATION lpTimeZoneInformation
433 )
434 {
435 // aprintf("GetTimeZoneInformation()\n");
436
437 // memset(lpTimeZoneInformation, 0, sizeof(TIME_ZONE_INFORMATION));
438
439 return TIME_ZONE_ID_UNKNOWN;
440 }
441
442 BOOL
443 STDCALL
444 SetTimeZoneInformation(
445 CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation
446 )
447 {
448
449 return FALSE;
450 }
451
452 DWORD STDCALL GetCurrentTime(VOID)
453 {
454 return GetTickCount ();
455 }
456
457 DWORD
458 STDCALL
459 GetTickCount(VOID)
460 {
461 ULONG UpTime;
462 NtGetTickCount (&UpTime);
463 return UpTime;
464 }
465
466 WINBOOL STDCALL
467 SystemTimeToTzSpecificLocalTime(
468 LPTIME_ZONE_INFORMATION lpTimeZoneInformation,
469 LPSYSTEMTIME lpUniversalTime,
470 LPSYSTEMTIME lpLocalTime
471 )
472 {
473 TIME_ZONE_INFORMATION TimeZoneInformation;
474 LPTIME_ZONE_INFORMATION lpTzInfo;
475 LARGE_INTEGER FileTime;
476
477 if (!lpTimeZoneInformation)
478 {
479 GetTimeZoneInformation (&TimeZoneInformation);
480 lpTzInfo = &TimeZoneInformation;
481 }
482 else
483 lpTzInfo = lpTimeZoneInformation;
484
485 if (!lpUniversalTime)
486 return FALSE;
487
488 if (!lpLocalTime)
489 return FALSE;
490
491 SystemTimeToFileTime (lpUniversalTime, (PFILETIME)&FileTime);
492 FileTime.QuadPart -= (lpTzInfo->Bias * TICKSPERMIN);
493 FileTimeToSystemTime ((PFILETIME)&FileTime, lpLocalTime);
494
495 return TRUE;
496 }
497
498 WINBOOL
499 STDCALL
500 GetSystemTimeAdjustment(
501 PDWORD lpTimeAdjustment,
502 PDWORD lpTimeIncrement,
503 PWINBOOL lpTimeAdjustmentDisabled
504 )
505 {
506 // FIXME: Preliminary default settings.
507 *lpTimeAdjustment = 0;
508 *lpTimeIncrement = 0;
509 *lpTimeAdjustmentDisabled = TRUE;
510
511 return TRUE;
512 }
513
514 WINBOOL
515 STDCALL
516 SetSystemTimeAdjustment(
517 DWORD dwTimeAdjustment,
518 WINBOOL bTimeAdjustmentDisabled
519 )
520 {
521
522 return TRUE;
523 }