1 /* $Id: time.c,v 1.13 2001/05/30 20:03:28 ekohl Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/misc/time.c
6 * PURPOSE: Time conversion functions
7 * PROGRAMMER: Boudewijn ( ariadne@xs4all.nl)
8 * DOSDATE and DOSTIME structures from Onno Hovers
13 /* INCLUDES ******************************************************************/
15 #include <ddk/ntddk.h>
17 #include <napi/shared_data.h>
18 #include <kernel32/error.h>
22 #include <kernel32/kernel32.h>
24 /* TYPES *********************************************************************/
26 typedef struct __DOSTIME
33 typedef struct __DOSDATE
40 #define TICKSPERMIN 600000000
41 #define TICKSPERSEC 10000000
42 #define TICKSPERMSEC 10000
43 #define SECSPERDAY 86400
44 #define SECSPERHOUR 3600
46 #define MINSPERHOUR 60
47 #define HOURSPERDAY 24
48 #define EPOCHWEEKDAY 0
50 #define EPOCHYEAR 1601
51 #define DAYSPERNORMALYEAR 365
52 #define DAYSPERLEAPYEAR 366
53 #define MONSPERYEAR 12
55 static const int YearLengths
[2] = {DAYSPERNORMALYEAR
, DAYSPERLEAPYEAR
};
56 static const int MonthLengths
[2][MONSPERYEAR
] =
58 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
59 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
62 static __inline
int IsLeapYear(int Year
)
64 return Year
% 4 == 0 && (Year
% 100 != 0 || Year
% 400 == 0) ? 1 : 0;
67 static __inline
void NormalizeTimeFields(WORD
*FieldToNormalize
,
71 *FieldToNormalize
= (WORD
) (*FieldToNormalize
- Modulus
);
72 *CarryField
= (WORD
) (*CarryField
+ 1);
75 #define LISECOND RtlEnlargedUnsignedMultiply(SECOND,NSPERSEC)
76 #define LIMINUTE RtlEnlargedUnsignedMultiply(MINUTE,NSPERSEC)
77 #define LIHOUR RtlEnlargedUnsignedMultiply(HOUR,NSPERSEC)
78 #define LIDAY RtlEnlargedUnsignedMultiply(DAY,NSPERSEC)
79 #define LIYEAR RtlEnlargedUnsignedMultiply(YEAR,NSPERSEC)
80 #define LIFOURYEAR RtlEnlargedUnsignedMultiply(FOURYEAR,NSPERSEC)
81 #define LICENTURY RtlEnlargedUnsignedMultiply(CENTURY,NSPERSEC)
82 #define LIMILLENIUM RtlEnlargedUnsignedMultiply(CENTURY,10*NSPERSEC)
87 /* FUNCTIONS ****************************************************************/
91 FileTimeToDosDateTime(
92 CONST FILETIME
*lpFileTime
,
97 PDOSTIME pdtime
=(PDOSTIME
) lpFatTime
;
98 PDOSDATE pddate
=(PDOSDATE
) lpFatDate
;
99 SYSTEMTIME SystemTime
;
101 if ( lpFileTime
== NULL
)
104 if ( lpFatDate
== NULL
)
107 if ( lpFatTime
== NULL
)
110 FileTimeToSystemTime(
115 pdtime
->Second
= SystemTime
.wSecond
;
116 pdtime
->Minute
= SystemTime
.wMinute
;
117 pdtime
->Hour
= SystemTime
.wHour
;
119 pddate
->Day
= SystemTime
.wDay
;
120 pddate
->Month
= SystemTime
.wMonth
;
121 pddate
->Year
= SystemTime
.wYear
- 1980;
128 DosDateTimeToFileTime(
131 LPFILETIME lpFileTime
134 PDOSTIME pdtime
= (PDOSTIME
) &wFatTime
;
135 PDOSDATE pddate
= (PDOSDATE
) &wFatDate
;
136 SYSTEMTIME SystemTime
;
138 if ( lpFileTime
== NULL
)
141 SystemTime
.wMilliseconds
= 0;
142 SystemTime
.wSecond
= pdtime
->Second
;
143 SystemTime
.wMinute
= pdtime
->Minute
;
144 SystemTime
.wHour
= pdtime
->Hour
;
146 SystemTime
.wDay
= pddate
->Day
;
147 SystemTime
.wMonth
= pddate
->Month
;
148 SystemTime
.wYear
= 1980 + pddate
->Year
;
150 SystemTimeToFileTime(&SystemTime
,lpFileTime
);
158 CONST FILETIME
*lpFileTime1
,
159 CONST FILETIME
*lpFileTime2
162 if ( lpFileTime1
== NULL
)
164 if ( lpFileTime2
== NULL
)
167 if (*((PLONGLONG
)lpFileTime1
) > *((PLONGLONG
)lpFileTime2
))
169 else if (*((PLONGLONG
)lpFileTime1
) < *((PLONGLONG
)lpFileTime2
))
177 GetSystemTimeAsFileTime(PFILETIME lpFileTime
)
179 NtQuerySystemTime ((TIME
*)lpFileTime
);
184 SystemTimeToFileTime(
185 CONST SYSTEMTIME
* lpSystemTime
,
186 LPFILETIME lpFileTime
190 int CurYear
, CurMonth
, MonthLength
;
191 long long int rcTime
;
192 SYSTEMTIME SystemTime
;
194 memcpy (&SystemTime
, lpSystemTime
, sizeof(SYSTEMTIME
));
198 /* FIXME: normalize the TIME_FIELDS structure here */
199 while (SystemTime
.wSecond
>= SECSPERMIN
)
201 NormalizeTimeFields(&SystemTime
.wSecond
,
205 while (SystemTime
.wMinute
>= MINSPERHOUR
)
207 NormalizeTimeFields(&SystemTime
.wMinute
,
211 while (SystemTime
.wHour
>= HOURSPERDAY
)
213 NormalizeTimeFields(&SystemTime
.wHour
,
218 MonthLengths
[IsLeapYear(SystemTime
.wYear
)][SystemTime
.wMonth
- 1];
219 while (SystemTime
.wDay
> MonthLength
)
221 NormalizeTimeFields(&SystemTime
.wDay
,
225 while (SystemTime
.wMonth
> MONSPERYEAR
)
227 NormalizeTimeFields(&SystemTime
.wMonth
,
232 /* FIXME: handle calendar corrections here */
233 for (CurYear
= EPOCHYEAR
; CurYear
< SystemTime
.wYear
; CurYear
++)
235 rcTime
+= YearLengths
[IsLeapYear(CurYear
)];
237 for (CurMonth
= 1; CurMonth
< SystemTime
.wMonth
; CurMonth
++)
239 rcTime
+= MonthLengths
[IsLeapYear(CurYear
)][CurMonth
- 1];
241 rcTime
+= SystemTime
.wDay
- 1;
242 rcTime
*= SECSPERDAY
;
243 rcTime
+= SystemTime
.wHour
* SECSPERHOUR
+
244 SystemTime
.wMinute
* SECSPERMIN
+ SystemTime
.wSecond
;
245 rcTime
*= TICKSPERSEC
;
246 rcTime
+= SystemTime
.wMilliseconds
* TICKSPERMSEC
;
248 *lpFileTime
= *(FILETIME
*)&rcTime
;
253 // dwDayOfWeek = RtlLargeIntegerDivide(FileTime,LIDAY,&dwRemDay);
254 // lpSystemTime->wDayOfWeek = 1 + GET_LARGE_INTEGER_LOW_PART(dwDayOfWeek) % 7;
260 FileTimeToSystemTime(
261 CONST FILETIME
*lpFileTime
,
262 LPSYSTEMTIME lpSystemTime
266 int LeapSecondCorrections
, SecondsInDay
, CurYear
;
267 int LeapYear
, CurMonth
;
269 long long int Time
= *((long long int*)lpFileTime
);
271 /* Extract millisecond from time and convert time into seconds */
272 lpSystemTime
->wMilliseconds
= (WORD
)((Time
% TICKSPERSEC
) / TICKSPERMSEC
);
273 Time
= Time
/ TICKSPERSEC
;
275 /* FIXME: Compute the number of leap second corrections here */
276 LeapSecondCorrections
= 0;
278 /* Split the time into days and seconds within the day */
279 Days
= Time
/ SECSPERDAY
;
280 SecondsInDay
= Time
% SECSPERDAY
;
282 /* Adjust the values for GMT and leap seconds */
283 SecondsInDay
+= LeapSecondCorrections
;
284 while (SecondsInDay
< 0)
286 SecondsInDay
+= SECSPERDAY
;
289 while (SecondsInDay
>= SECSPERDAY
)
291 SecondsInDay
-= SECSPERDAY
;
295 /* compute time of day */
296 lpSystemTime
->wHour
= (WORD
) (SecondsInDay
/ SECSPERHOUR
);
297 SecondsInDay
= SecondsInDay
% SECSPERHOUR
;
298 lpSystemTime
->wMinute
= (WORD
) (SecondsInDay
/ SECSPERMIN
);
299 lpSystemTime
->wSecond
= (WORD
) (SecondsInDay
% SECSPERMIN
);
301 /* FIXME: handle the possibility that we are on a leap second (i.e. Second = 60) */
303 /* compute day of week */
304 lpSystemTime
->wDayOfWeek
= (WORD
) ((EPOCHWEEKDAY
+ Days
) % DAYSPERWEEK
);
308 /* FIXME: handle calendar modifications */
311 LeapYear
= IsLeapYear(CurYear
);
312 if (Days
< (long) YearLengths
[LeapYear
])
317 Days
= Days
- (long) YearLengths
[LeapYear
];
319 lpSystemTime
->wYear
= (WORD
) CurYear
;
321 /* Compute month of year */
322 Months
= MonthLengths
[LeapYear
];
323 for (CurMonth
= 0; Days
>= (long) Months
[CurMonth
]; CurMonth
++)
324 Days
= Days
- (long) Months
[CurMonth
];
325 lpSystemTime
->wMonth
= (WORD
) (CurMonth
+ 1);
326 lpSystemTime
->wDay
= (WORD
) (Days
+ 1);
334 FileTimeToLocalFileTime(
335 CONST FILETIME
*lpFileTime
,
336 LPFILETIME lpLocalFileTime
339 // FIXME: include time bias
340 *((PLONGLONG
)lpLocalFileTime
) = *((PLONGLONG
)lpFileTime
);
347 LocalFileTimeToFileTime(
348 CONST FILETIME
*lpLocalFileTime
,
349 LPFILETIME lpFileTime
352 // FIXME: include time bias
353 *((PLONGLONG
)lpFileTime
) = *((PLONGLONG
)lpLocalFileTime
);
360 GetLocalTime(LPSYSTEMTIME lpSystemTime
)
363 FILETIME LocalFileTime
;
365 NtQuerySystemTime ((TIME
*)&FileTime
);
366 FileTimeToLocalFileTime (&FileTime
, &LocalFileTime
);
367 FileTimeToSystemTime (&LocalFileTime
, lpSystemTime
);
372 GetSystemTime(LPSYSTEMTIME lpSystemTime
)
376 NtQuerySystemTime ((TIME
*)&FileTime
);
377 FileTimeToSystemTime (&FileTime
, lpSystemTime
);
382 SetLocalTime(CONST SYSTEMTIME
*lpSystemTime
)
384 FILETIME LocalFileTime
;
385 LARGE_INTEGER FileTime
;
388 SystemTimeToFileTime (lpSystemTime
, &LocalFileTime
);
389 LocalFileTimeToFileTime (&LocalFileTime
, (FILETIME
*)&FileTime
);
390 errCode
= NtSetSystemTime (&FileTime
, &FileTime
);
391 if (!NT_SUCCESS(errCode
))
398 SetSystemTime(CONST SYSTEMTIME
*lpSystemTime
)
400 LARGE_INTEGER NewSystemTime
;
403 SystemTimeToFileTime (lpSystemTime
, (PFILETIME
)&NewSystemTime
);
404 errCode
= NtSetSystemTime (&NewSystemTime
, &NewSystemTime
);
405 if (!NT_SUCCESS(errCode
))
412 GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation
)
414 TIME_ZONE_INFORMATION TimeZoneInformation
;
417 DPRINT("GetTimeZoneInformation()\n");
419 Status
= NtQuerySystemInformation(SystemCurrentTimeZoneInformation
,
420 &TimeZoneInformation
,
421 sizeof(TIME_ZONE_INFORMATION
),
423 if (!NT_SUCCESS(Status
))
425 SetLastErrorByStatus(Status
);
426 return TIME_ZONE_ID_INVALID
;
429 memcpy(lpTimeZoneInformation
,
430 &TimeZoneInformation
,
431 sizeof(TIME_ZONE_INFORMATION
));
433 return ((PKUSER_SHARED_DATA
)USER_SHARED_DATA_BASE
)->TimeZoneId
;
438 SetTimeZoneInformation(CONST TIME_ZONE_INFORMATION
*lpTimeZoneInformation
)
440 TIME_ZONE_INFORMATION TimeZoneInformation
;
443 DPRINT("SetTimeZoneInformation()\n");
445 memcpy(&TimeZoneInformation
,
446 lpTimeZoneInformation
,
447 sizeof(TIME_ZONE_INFORMATION
));
449 Status
= RtlSetTimeZoneInformation(&TimeZoneInformation
);
450 if (!NT_SUCCESS(Status
))
452 SetLastErrorByStatus(Status
);
456 NtSetSystemTime(0,0);
465 return GetTickCount();
473 NtGetTickCount(&UpTime
);
479 SystemTimeToTzSpecificLocalTime(
480 LPTIME_ZONE_INFORMATION lpTimeZoneInformation
,
481 LPSYSTEMTIME lpUniversalTime
,
482 LPSYSTEMTIME lpLocalTime
485 TIME_ZONE_INFORMATION TimeZoneInformation
;
486 LPTIME_ZONE_INFORMATION lpTzInfo
;
487 LARGE_INTEGER FileTime
;
489 if (!lpTimeZoneInformation
)
491 GetTimeZoneInformation (&TimeZoneInformation
);
492 lpTzInfo
= &TimeZoneInformation
;
495 lpTzInfo
= lpTimeZoneInformation
;
497 if (!lpUniversalTime
)
503 SystemTimeToFileTime (lpUniversalTime
, (PFILETIME
)&FileTime
);
504 FileTime
.QuadPart
-= (lpTzInfo
->Bias
* TICKSPERMIN
);
505 FileTimeToSystemTime ((PFILETIME
)&FileTime
, lpLocalTime
);
512 GetSystemTimeAdjustment(PDWORD lpTimeAdjustment
,
513 PDWORD lpTimeIncrement
,
514 PWINBOOL lpTimeAdjustmentDisabled
)
516 SYSTEM_QUERY_TIME_ADJUSTMENT Buffer
;
519 Status
= NtQuerySystemInformation(SystemTimeAdjustmentInformation
,
521 sizeof(SYSTEM_QUERY_TIME_ADJUSTMENT
),
523 if (!NT_SUCCESS(Status
))
525 SetLastErrorByStatus(Status
);
529 *lpTimeAdjustment
= (DWORD
)Buffer
.TimeAdjustment
;
530 *lpTimeIncrement
= (DWORD
)Buffer
.MaximumIncrement
;
531 *lpTimeAdjustmentDisabled
= (WINBOOL
)Buffer
.TimeSynchronization
;
538 SetSystemTimeAdjustment(DWORD dwTimeAdjustment
,
539 WINBOOL bTimeAdjustmentDisabled
)
542 SYSTEM_TIME_ADJUSTMENT_INFO Buffer
;
544 Buffer
.TimeAdjustment
= (ULONG
)dwTimeAdjustment
;
545 Buffer
.TimeSynchronization
= (BOOLEAN
)bTimeAdjustmentDisabled
;
547 Status
= NtSetSystemInformation(SystemTimeAdjustmentInformation
,
549 sizeof(SYSTEM_TIME_ADJUSTMENT_INFO
));
550 if (!NT_SUCCESS(Status
))
552 SetLastErrorByStatus(Status
);