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
12 /* INCLUDES ******************************************************************/
14 #include <ddk/ntddk.h>
16 #include <internal/string.h>
20 #include <kernel32/kernel32.h>
22 /* TYPES *********************************************************************/
24 typedef struct __DOSTIME
31 typedef struct __DOSDATE
38 #define TICKSPERMIN 600000000
39 #define TICKSPERSEC 10000000
40 #define TICKSPERMSEC 10000
41 #define SECSPERDAY 86400
42 #define SECSPERHOUR 3600
44 #define MINSPERHOUR 60
45 #define HOURSPERDAY 24
46 #define EPOCHWEEKDAY 0
48 #define EPOCHYEAR 1601
49 #define DAYSPERNORMALYEAR 365
50 #define DAYSPERLEAPYEAR 366
51 #define MONSPERYEAR 12
53 static const int YearLengths
[2] = {DAYSPERNORMALYEAR
, DAYSPERLEAPYEAR
};
54 static const int MonthLengths
[2][MONSPERYEAR
] =
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 }
60 static __inline
int IsLeapYear(int Year
)
62 return Year
% 4 == 0 && (Year
% 100 != 0 || Year
% 400 == 0) ? 1 : 0;
65 static __inline
void NormalizeTimeFields(WORD
*FieldToNormalize
,
69 *FieldToNormalize
= (WORD
) (*FieldToNormalize
- Modulus
);
70 *CarryField
= (WORD
) (*CarryField
+ 1);
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)
85 /* FUNCTIONS ****************************************************************/
89 FileTimeToDosDateTime(
90 CONST FILETIME
*lpFileTime
,
95 PDOSTIME pdtime
=(PDOSTIME
) lpFatTime
;
96 PDOSDATE pddate
=(PDOSDATE
) lpFatDate
;
97 SYSTEMTIME SystemTime
;
99 if ( lpFileTime
== NULL
)
102 if ( lpFatDate
== NULL
)
105 if ( lpFatTime
== NULL
)
108 FileTimeToSystemTime(
113 pdtime
->Second
= SystemTime
.wSecond
;
114 pdtime
->Minute
= SystemTime
.wMinute
;
115 pdtime
->Hour
= SystemTime
.wHour
;
117 pddate
->Day
= SystemTime
.wDay
;
118 pddate
->Month
= SystemTime
.wMonth
;
119 pddate
->Year
= SystemTime
.wYear
- 1980;
126 DosDateTimeToFileTime(
129 LPFILETIME lpFileTime
132 PDOSTIME pdtime
= (PDOSTIME
) &wFatTime
;
133 PDOSDATE pddate
= (PDOSDATE
) &wFatDate
;
134 SYSTEMTIME SystemTime
;
136 if ( lpFileTime
== NULL
)
139 SystemTime
.wMilliseconds
= 0;
140 SystemTime
.wSecond
= pdtime
->Second
;
141 SystemTime
.wMinute
= pdtime
->Minute
;
142 SystemTime
.wHour
= pdtime
->Hour
;
144 SystemTime
.wDay
= pddate
->Day
;
145 SystemTime
.wMonth
= pddate
->Month
;
146 SystemTime
.wYear
= 1980 + pddate
->Year
;
148 SystemTimeToFileTime(&SystemTime
,lpFileTime
);
156 CONST FILETIME
*lpFileTime1
,
157 CONST FILETIME
*lpFileTime2
160 if ( lpFileTime1
== NULL
)
162 if ( lpFileTime2
== NULL
)
165 if (*((PLONGLONG
)lpFileTime1
) > *((PLONGLONG
)lpFileTime2
))
167 else if (*((PLONGLONG
)lpFileTime1
) < *((PLONGLONG
)lpFileTime2
))
175 GetSystemTimeAsFileTime(PFILETIME lpFileTime
)
177 NtQuerySystemTime ((TIME
*)lpFileTime
);
182 SystemTimeToFileTime(
183 CONST SYSTEMTIME
* lpSystemTime
,
184 LPFILETIME lpFileTime
188 int CurYear
, CurMonth
, MonthLength
;
189 long long int rcTime
;
190 SYSTEMTIME SystemTime
;
192 memcpy (&SystemTime
, lpSystemTime
, sizeof(SYSTEMTIME
));
196 /* FIXME: normalize the TIME_FIELDS structure here */
197 while (SystemTime
.wSecond
>= SECSPERMIN
)
199 NormalizeTimeFields(&SystemTime
.wSecond
,
203 while (SystemTime
.wMinute
>= MINSPERHOUR
)
205 NormalizeTimeFields(&SystemTime
.wMinute
,
209 while (SystemTime
.wHour
>= HOURSPERDAY
)
211 NormalizeTimeFields(&SystemTime
.wHour
,
216 MonthLengths
[IsLeapYear(SystemTime
.wYear
)][SystemTime
.wMonth
- 1];
217 while (SystemTime
.wDay
> MonthLength
)
219 NormalizeTimeFields(&SystemTime
.wDay
,
223 while (SystemTime
.wMonth
> MONSPERYEAR
)
225 NormalizeTimeFields(&SystemTime
.wMonth
,
230 /* FIXME: handle calendar corrections here */
231 for (CurYear
= EPOCHYEAR
; CurYear
< SystemTime
.wYear
; CurYear
++)
233 rcTime
+= YearLengths
[IsLeapYear(CurYear
)];
235 for (CurMonth
= 1; CurMonth
< SystemTime
.wMonth
; CurMonth
++)
237 rcTime
+= MonthLengths
[IsLeapYear(CurYear
)][CurMonth
- 1];
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
;
246 *lpFileTime
= *(FILETIME
*)&rcTime
;
251 // dwDayOfWeek = RtlLargeIntegerDivide(FileTime,LIDAY,&dwRemDay);
252 // lpSystemTime->wDayOfWeek = 1 + GET_LARGE_INTEGER_LOW_PART(dwDayOfWeek) % 7;
258 FileTimeToSystemTime(
259 CONST FILETIME
*lpFileTime
,
260 LPSYSTEMTIME lpSystemTime
264 int LeapSecondCorrections
, SecondsInDay
, CurYear
;
265 int LeapYear
, CurMonth
;
267 long long int Time
= *((long long int*)lpFileTime
);
269 /* Extract millisecond from time and convert time into seconds */
270 lpSystemTime
->wMilliseconds
= (WORD
)((Time
% TICKSPERSEC
) / TICKSPERMSEC
);
271 Time
= Time
/ TICKSPERSEC
;
273 /* FIXME: Compute the number of leap second corrections here */
274 LeapSecondCorrections
= 0;
276 /* Split the time into days and seconds within the day */
277 Days
= Time
/ SECSPERDAY
;
278 SecondsInDay
= Time
% SECSPERDAY
;
280 /* Adjust the values for GMT and leap seconds */
281 SecondsInDay
+= LeapSecondCorrections
;
282 while (SecondsInDay
< 0)
284 SecondsInDay
+= SECSPERDAY
;
287 while (SecondsInDay
>= SECSPERDAY
)
289 SecondsInDay
-= SECSPERDAY
;
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
);
299 /* FIXME: handle the possibility that we are on a leap second (i.e. Second = 60) */
301 /* compute day of week */
302 lpSystemTime
->wDayOfWeek
= (WORD
) ((EPOCHWEEKDAY
+ Days
) % DAYSPERWEEK
);
306 /* FIXME: handle calendar modifications */
309 LeapYear
= IsLeapYear(CurYear
);
310 if (Days
< (long) YearLengths
[LeapYear
])
315 Days
= Days
- (long) YearLengths
[LeapYear
];
317 lpSystemTime
->wYear
= (WORD
) CurYear
;
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);
332 FileTimeToLocalFileTime(
333 CONST FILETIME
*lpFileTime
,
334 LPFILETIME lpLocalFileTime
337 // FIXME: include time bias
338 *((PLONGLONG
)lpLocalFileTime
) = *((PLONGLONG
)lpFileTime
);
345 LocalFileTimeToFileTime(
346 CONST FILETIME
*lpLocalFileTime
,
347 LPFILETIME lpFileTime
350 // FIXME: include time bias
351 *((PLONGLONG
)lpFileTime
) = *((PLONGLONG
)lpLocalFileTime
);
359 LPSYSTEMTIME lpSystemTime
363 FILETIME LocalFileTime
;
365 NtQuerySystemTime ((TIME
*)&FileTime
);
366 FileTimeToLocalFileTime (&FileTime
, &LocalFileTime
);
367 FileTimeToSystemTime (&LocalFileTime
, lpSystemTime
);
373 LPSYSTEMTIME lpSystemTime
378 NtQuerySystemTime ((TIME
*)&FileTime
);
379 FileTimeToSystemTime (&FileTime
, lpSystemTime
);
385 CONST SYSTEMTIME
*lpSystemTime
388 FILETIME LocalFileTime
;
389 LARGE_INTEGER FileTime
;
392 SystemTimeToFileTime (lpSystemTime
, &LocalFileTime
);
393 LocalFileTimeToFileTime (&LocalFileTime
, (FILETIME
*)&FileTime
);
394 errCode
= NtSetSystemTime (&FileTime
, &FileTime
);
395 if (!NT_SUCCESS(errCode
))
403 CONST SYSTEMTIME
*lpSystemTime
406 LARGE_INTEGER NewSystemTime
;
409 SystemTimeToFileTime (lpSystemTime
, (PFILETIME
)&NewSystemTime
);
410 errCode
= NtSetSystemTime (&NewSystemTime
, &NewSystemTime
);
411 if (!NT_SUCCESS(errCode
))
417 typedef struct _TIME_ZONE_INFORMATION { // tzi
419 WCHAR StandardName[ 32 ];
420 SYSTEMTIME StandardDate;
422 WCHAR DaylightName[ 32 ];
423 SYSTEMTIME DaylightDate;
425 } TIME_ZONE_INFORMATION;
426 TIME_ZONE_INFORMATION TimeZoneInformation = {60,"CET",;
431 GetTimeZoneInformation(
432 LPTIME_ZONE_INFORMATION lpTimeZoneInformation
435 // aprintf("GetTimeZoneInformation()\n");
437 // memset(lpTimeZoneInformation, 0, sizeof(TIME_ZONE_INFORMATION));
439 return TIME_ZONE_ID_UNKNOWN
;
444 SetTimeZoneInformation(
445 CONST TIME_ZONE_INFORMATION
*lpTimeZoneInformation
452 DWORD STDCALL
GetCurrentTime(VOID
)
454 return GetTickCount ();
462 NtGetTickCount (&UpTime
);
467 SystemTimeToTzSpecificLocalTime(
468 LPTIME_ZONE_INFORMATION lpTimeZoneInformation
,
469 LPSYSTEMTIME lpUniversalTime
,
470 LPSYSTEMTIME lpLocalTime
473 TIME_ZONE_INFORMATION TimeZoneInformation
;
474 LPTIME_ZONE_INFORMATION lpTzInfo
;
475 LARGE_INTEGER FileTime
;
477 if (!lpTimeZoneInformation
)
479 GetTimeZoneInformation (&TimeZoneInformation
);
480 lpTzInfo
= &TimeZoneInformation
;
483 lpTzInfo
= lpTimeZoneInformation
;
485 if (!lpUniversalTime
)
491 SystemTimeToFileTime (lpUniversalTime
, (PFILETIME
)&FileTime
);
492 FileTime
.QuadPart
-= (lpTzInfo
->Bias
* TICKSPERMIN
);
493 FileTimeToSystemTime ((PFILETIME
)&FileTime
, lpLocalTime
);
500 GetSystemTimeAdjustment(
501 PDWORD lpTimeAdjustment
,
502 PDWORD lpTimeIncrement
,
503 PWINBOOL lpTimeAdjustmentDisabled
506 // FIXME: Preliminary default settings.
507 *lpTimeAdjustment
= 0;
508 *lpTimeIncrement
= 0;
509 *lpTimeAdjustmentDisabled
= TRUE
;
516 SetSystemTimeAdjustment(
517 DWORD dwTimeAdjustment
,
518 WINBOOL bTimeAdjustmentDisabled