1 /* $Id: time.c,v 1.1 2004/05/31 19:29:02 gdalsnes Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
6 * PURPOSE: Conversion between Time and TimeFields
7 * PROGRAMMER: Rex Jolliff (rex@lvcablemodem.com)
10 * 08/03/98 RJJ Implemented these functions
13 /* INCLUDES *****************************************************************/
15 #include <ddk/ntddk.h>
16 #include <ntdll/rtl.h>
21 #define TICKSPERMIN 600000000
22 #define TICKSPERSEC 10000000
23 #define TICKSPERMSEC 10000
24 #define SECSPERDAY 86400
25 #define SECSPERHOUR 3600
27 #define MINSPERHOUR 60
28 #define HOURSPERDAY 24
29 #define EPOCHWEEKDAY 1
31 #define EPOCHYEAR 1601
32 #define DAYSPERNORMALYEAR 365
33 #define DAYSPERLEAPYEAR 366
34 #define MONSPERYEAR 12
37 #define TICKSTO1970 0x019db1ded53e8000LL
38 #define TICKSTO1980 0x01a8e79fe1d58000LL
40 #define TICKSTO1970 0x019db1ded53e8000i64
41 #define TICKSTO1980 0x01a8e79fe1d58000i64
45 static const int YearLengths
[2] =
47 DAYSPERNORMALYEAR
, DAYSPERLEAPYEAR
49 static const int MonthLengths
[2][MONSPERYEAR
] =
52 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
54 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
57 static __inline
int IsLeapYear(int Year
)
59 return Year
% 4 == 0 && (Year
% 100 != 0 || Year
% 400 == 0) ? 1 : 0;
62 static __inline
void NormalizeTimeFields(CSHORT
*FieldToNormalize
,
66 *FieldToNormalize
= (CSHORT
) (*FieldToNormalize
- Modulus
);
67 *CarryField
= (CSHORT
) (*CarryField
+ 1);
70 /* FUNCTIONS *****************************************************************/
78 PTIME_FIELDS tfTimeFields
,
91 TIME_FIELDS TimeFields
= *tfTimeFields
;
95 /* FIXME: normalize the TIME_FIELDS structure here */
96 while (TimeFields
.Second
>= SECSPERMIN
)
98 NormalizeTimeFields(&TimeFields
.Second
,
102 while (TimeFields
.Minute
>= MINSPERHOUR
)
104 NormalizeTimeFields(&TimeFields
.Minute
,
108 while (TimeFields
.Hour
>= HOURSPERDAY
)
110 NormalizeTimeFields(&TimeFields
.Hour
,
114 while (TimeFields
.Day
>
115 MonthLengths
[IsLeapYear(TimeFields
.Year
)][TimeFields
.Month
- 1])
117 NormalizeTimeFields(&TimeFields
.Day
,
121 while (TimeFields
.Month
> MONSPERYEAR
)
123 NormalizeTimeFields(&TimeFields
.Month
,
128 /* FIXME: handle calendar corrections here */
129 for (CurYear
= EPOCHYEAR
; CurYear
< TimeFields
.Year
; CurYear
++)
131 rcTime
+= YearLengths
[IsLeapYear(CurYear
)];
133 for (CurMonth
= 1; CurMonth
< TimeFields
.Month
; CurMonth
++)
135 rcTime
+= MonthLengths
[IsLeapYear(CurYear
)][CurMonth
- 1];
137 rcTime
+= TimeFields
.Day
- 1;
138 rcTime
*= SECSPERDAY
;
139 rcTime
+= TimeFields
.Hour
* SECSPERHOUR
+ TimeFields
.Minute
* SECSPERMIN
+
141 rcTime
*= TICKSPERSEC
;
142 rcTime
+= TimeFields
.Milliseconds
* TICKSPERMSEC
;
143 *Time
= *(LARGE_INTEGER
*)&rcTime
;
155 RtlTimeToElapsedTimeFields(IN PLARGE_INTEGER Time
,
156 OUT PTIME_FIELDS TimeFields
)
158 ULONGLONG ElapsedSeconds
;
160 ULONG SecondsInMinute
;
162 /* Extract millisecond from time */
163 TimeFields
->Milliseconds
= (CSHORT
)((Time
->QuadPart
% TICKSPERSEC
) / TICKSPERMSEC
);
165 /* Compute elapsed seconds */
166 ElapsedSeconds
= (ULONGLONG
)Time
->QuadPart
/ TICKSPERSEC
;
168 /* Compute seconds within the day */
169 SecondsInDay
= ElapsedSeconds
% SECSPERDAY
;
171 /* Compute elapsed minutes within the day */
172 SecondsInMinute
= SecondsInDay
% SECSPERHOUR
;
174 /* Compute elapsed time of day */
175 TimeFields
->Hour
= (CSHORT
)(SecondsInDay
/ SECSPERHOUR
);
176 TimeFields
->Minute
= (CSHORT
)(SecondsInMinute
/ SECSPERMIN
);
177 TimeFields
->Second
= (CSHORT
)(SecondsInMinute
% SECSPERMIN
);
179 /* Compute elapsed days */
180 TimeFields
->Day
= (CSHORT
)(ElapsedSeconds
/ SECSPERDAY
);
182 /* The elapsed number of months and days cannot be calculated */
183 TimeFields
->Month
= 0;
184 TimeFields
->Year
= 0;
195 PLARGE_INTEGER liTime
,
196 PTIME_FIELDS TimeFields
)
199 int LeapSecondCorrections
, SecondsInDay
, CurYear
;
200 int LeapYear
, CurMonth
, GMTOffset
;
202 #if defined(__GNUC__)
204 long long int Time
= (long long int)liTime
->QuadPart
;
207 __int64 Time
= (__int64
)liTime
->QuadPart
;
210 /* Extract millisecond from time and convert time into seconds */
211 TimeFields
->Milliseconds
= (CSHORT
) ((Time
% TICKSPERSEC
) / TICKSPERMSEC
);
212 Time
= Time
/ TICKSPERSEC
;
214 /* FIXME: Compute the number of leap second corrections here */
215 LeapSecondCorrections
= 0;
217 /* FIXME: get the GMT offset here */
220 /* Split the time into days and seconds within the day */
221 Days
= Time
/ SECSPERDAY
;
222 SecondsInDay
= Time
% SECSPERDAY
;
224 /* Adjust the values for GMT and leap seconds */
225 SecondsInDay
+= (GMTOffset
- LeapSecondCorrections
);
226 while (SecondsInDay
< 0)
228 SecondsInDay
+= SECSPERDAY
;
231 while (SecondsInDay
>= SECSPERDAY
)
233 SecondsInDay
-= SECSPERDAY
;
237 /* compute time of day */
238 TimeFields
->Hour
= (CSHORT
) (SecondsInDay
/ SECSPERHOUR
);
239 SecondsInDay
= SecondsInDay
% SECSPERHOUR
;
240 TimeFields
->Minute
= (CSHORT
) (SecondsInDay
/ SECSPERMIN
);
241 TimeFields
->Second
= (CSHORT
) (SecondsInDay
% SECSPERMIN
);
243 /* FIXME: handle the possibility that we are on a leap second (i.e. Second = 60) */
245 /* compute day of week */
246 TimeFields
->Weekday
= (CSHORT
) ((EPOCHWEEKDAY
+ Days
) % DAYSPERWEEK
);
250 CurYear
+= Days
/ DAYSPERLEAPYEAR
;
251 Days
-= (CurYear
- EPOCHYEAR
) * DAYSPERLEAPYEAR
;
252 CurYear
--; /* The next calculation needs CurYear - 1 */
253 Days
+= CurYear
- CurYear
/ 4 + CurYear
/ 100 - CurYear
/ 400;
255 Days
-= EPOCHYEAR
- 1 - (EPOCHYEAR
-1) / 4 + (EPOCHYEAR
-1) / 100 - (EPOCHYEAR
- 1) / 400;
256 /* FIXME: handle calendar modifications */
259 LeapYear
= IsLeapYear(CurYear
);
260 if (Days
< (long) YearLengths
[LeapYear
])
265 Days
= Days
- (long) YearLengths
[LeapYear
];
267 TimeFields
->Year
= (CSHORT
) CurYear
;
269 /* Compute month of year */
270 LeapYear
= IsLeapYear(CurYear
);
271 Months
= MonthLengths
[LeapYear
];
272 for (CurMonth
= 0; Days
>= (long) Months
[CurMonth
]; CurMonth
++)
273 Days
= Days
- (long) Months
[CurMonth
];
274 TimeFields
->Month
= (CSHORT
) (CurMonth
+ 1);
275 TimeFields
->Day
= (CSHORT
) (Days
+ 1);
284 RtlTimeToSecondsSince1970(
286 PULONG SecondsSince1970
)
288 LARGE_INTEGER liTime
;
290 liTime
.QuadPart
= Time
->QuadPart
- TICKSTO1970
;
291 liTime
.QuadPart
= liTime
.QuadPart
/ TICKSPERSEC
;
293 if (liTime
.u
.HighPart
!= 0)
296 *SecondsSince1970
= liTime
.u
.LowPart
;
307 RtlTimeToSecondsSince1980(
309 PULONG SecondsSince1980
)
311 LARGE_INTEGER liTime
;
313 liTime
.QuadPart
= Time
->QuadPart
- TICKSTO1980
;
314 liTime
.QuadPart
= liTime
.QuadPart
/ TICKSPERSEC
;
316 if (liTime
.u
.HighPart
!= 0)
319 *SecondsSince1980
= liTime
.u
.LowPart
;
330 RtlLocalTimeToSystemTime(PLARGE_INTEGER LocalTime
,
331 PLARGE_INTEGER SystemTime
)
333 SYSTEM_TIMEOFDAY_INFORMATION TimeInformation
;
336 Status
= NtQuerySystemInformation(SystemTimeOfDayInformation
,
338 sizeof(SYSTEM_TIMEOFDAY_INFORMATION
),
340 if (!NT_SUCCESS(Status
))
343 SystemTime
->QuadPart
= LocalTime
->QuadPart
+
344 TimeInformation
.TimeZoneBias
.QuadPart
;
346 return(STATUS_SUCCESS
);
357 RtlSystemTimeToLocalTime(PLARGE_INTEGER SystemTime
,
358 PLARGE_INTEGER LocalTime
)
360 SYSTEM_TIMEOFDAY_INFORMATION TimeInformation
;
363 Status
= NtQuerySystemInformation(SystemTimeOfDayInformation
,
365 sizeof(SYSTEM_TIMEOFDAY_INFORMATION
),
367 if (!NT_SUCCESS(Status
))
370 LocalTime
->QuadPart
= SystemTime
->QuadPart
-
371 TimeInformation
.TimeZoneBias
.QuadPart
;
373 return(STATUS_SUCCESS
);
382 RtlSecondsSince1970ToTime(
383 ULONG SecondsSince1970
,
388 llTime
= (SecondsSince1970
* TICKSPERSEC
) + TICKSTO1970
;
390 *Time
= *(LARGE_INTEGER
*)&llTime
;
399 RtlSecondsSince1980ToTime(
400 ULONG SecondsSince1980
,
405 llTime
= (SecondsSince1980
* TICKSPERSEC
) + TICKSTO1980
;
407 *Time
= *(LARGE_INTEGER
*)&llTime
;