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 TimeFields
,
83 TIME_FIELDS IntTimeFields
;
86 memcpy(&IntTimeFields
,
90 /* Normalize the TIME_FIELDS structure here */
91 while (IntTimeFields
.Second
>= SECSPERMIN
)
93 NormalizeTimeFields(&IntTimeFields
.Second
,
94 &IntTimeFields
.Minute
,
97 while (IntTimeFields
.Minute
>= MINSPERHOUR
)
99 NormalizeTimeFields(&IntTimeFields
.Minute
,
103 while (IntTimeFields
.Hour
>= HOURSPERDAY
)
105 NormalizeTimeFields(&IntTimeFields
.Hour
,
109 while (IntTimeFields
.Day
>
110 MonthLengths
[IsLeapYear(IntTimeFields
.Year
)][IntTimeFields
.Month
- 1])
112 NormalizeTimeFields(&IntTimeFields
.Day
,
113 &IntTimeFields
.Month
,
116 while (IntTimeFields
.Month
> MONSPERYEAR
)
118 NormalizeTimeFields(&IntTimeFields
.Month
,
123 /* Compute the time */
124 for (CurYear
= EPOCHYEAR
; CurYear
< IntTimeFields
.Year
; CurYear
++)
126 Time
->QuadPart
+= YearLengths
[IsLeapYear(CurYear
)];
128 for (CurMonth
= 1; CurMonth
< IntTimeFields
.Month
; CurMonth
++)
130 Time
->QuadPart
+= MonthLengths
[IsLeapYear(CurYear
)][CurMonth
- 1];
132 Time
->QuadPart
+= IntTimeFields
.Day
- 1;
133 Time
->QuadPart
*= SECSPERDAY
;
134 Time
->QuadPart
+= IntTimeFields
.Hour
* SECSPERHOUR
+ IntTimeFields
.Minute
* SECSPERMIN
+
135 IntTimeFields
.Second
;
136 Time
->QuadPart
*= TICKSPERSEC
;
137 Time
->QuadPart
+= IntTimeFields
.Milliseconds
* TICKSPERMSEC
;
148 RtlTimeToElapsedTimeFields(IN PLARGE_INTEGER Time
,
149 OUT PTIME_FIELDS TimeFields
)
151 ULONGLONG ElapsedSeconds
;
153 ULONG SecondsInMinute
;
155 /* Extract millisecond from time */
156 TimeFields
->Milliseconds
= (CSHORT
)((Time
->QuadPart
% TICKSPERSEC
) / TICKSPERMSEC
);
158 /* Compute elapsed seconds */
159 ElapsedSeconds
= (ULONGLONG
)Time
->QuadPart
/ TICKSPERSEC
;
161 /* Compute seconds within the day */
162 SecondsInDay
= ElapsedSeconds
% SECSPERDAY
;
164 /* Compute elapsed minutes within the day */
165 SecondsInMinute
= SecondsInDay
% SECSPERHOUR
;
167 /* Compute elapsed time of day */
168 TimeFields
->Hour
= (CSHORT
)(SecondsInDay
/ SECSPERHOUR
);
169 TimeFields
->Minute
= (CSHORT
)(SecondsInMinute
/ SECSPERMIN
);
170 TimeFields
->Second
= (CSHORT
)(SecondsInMinute
% SECSPERMIN
);
172 /* Compute elapsed days */
173 TimeFields
->Day
= (CSHORT
)(ElapsedSeconds
/ SECSPERDAY
);
175 /* The elapsed number of months and days cannot be calculated */
176 TimeFields
->Month
= 0;
177 TimeFields
->Year
= 0;
188 PTIME_FIELDS TimeFields
)
191 int SecondsInDay
, CurYear
;
192 int LeapYear
, CurMonth
;
194 LONGLONG IntTime
= (LONGLONG
)Time
->QuadPart
;
196 /* Extract millisecond from time and convert time into seconds */
197 TimeFields
->Milliseconds
= (CSHORT
) ((IntTime
% TICKSPERSEC
) / TICKSPERMSEC
);
198 IntTime
= IntTime
/ TICKSPERSEC
;
200 /* Split the time into days and seconds within the day */
201 Days
= IntTime
/ SECSPERDAY
;
202 SecondsInDay
= IntTime
% SECSPERDAY
;
204 /* Adjust the values for days and seconds in day */
205 while (SecondsInDay
< 0)
207 SecondsInDay
+= SECSPERDAY
;
210 while (SecondsInDay
>= SECSPERDAY
)
212 SecondsInDay
-= SECSPERDAY
;
216 /* compute time of day */
217 TimeFields
->Hour
= (CSHORT
) (SecondsInDay
/ SECSPERHOUR
);
218 SecondsInDay
= SecondsInDay
% SECSPERHOUR
;
219 TimeFields
->Minute
= (CSHORT
) (SecondsInDay
/ SECSPERMIN
);
220 TimeFields
->Second
= (CSHORT
) (SecondsInDay
% SECSPERMIN
);
222 /* compute day of week */
223 TimeFields
->Weekday
= (CSHORT
) ((EPOCHWEEKDAY
+ Days
) % DAYSPERWEEK
);
227 CurYear
+= Days
/ DAYSPERLEAPYEAR
;
228 Days
-= (CurYear
- EPOCHYEAR
) * DAYSPERLEAPYEAR
;
229 CurYear
--; /* The next calculation needs CurYear - 1 */
230 Days
+= CurYear
- CurYear
/ 4 + CurYear
/ 100 - CurYear
/ 400;
232 Days
-= EPOCHYEAR
- 1 - (EPOCHYEAR
-1) / 4 + (EPOCHYEAR
-1) / 100 - (EPOCHYEAR
- 1) / 400;
233 /* FIXME: handle calendar modifications */
236 LeapYear
= IsLeapYear(CurYear
);
237 if (Days
< (long) YearLengths
[LeapYear
])
242 Days
= Days
- (long) YearLengths
[LeapYear
];
244 TimeFields
->Year
= (CSHORT
) CurYear
;
246 /* Compute month of year */
247 LeapYear
= IsLeapYear(CurYear
);
248 Months
= MonthLengths
[LeapYear
];
249 for (CurMonth
= 0; Days
>= (long) Months
[CurMonth
]; CurMonth
++)
250 Days
= Days
- (long) Months
[CurMonth
];
251 TimeFields
->Month
= (CSHORT
) (CurMonth
+ 1);
252 TimeFields
->Day
= (CSHORT
) (Days
+ 1);
261 RtlTimeToSecondsSince1970(
263 PULONG SecondsSince1970
)
265 LARGE_INTEGER IntTime
;
267 IntTime
.QuadPart
= Time
->QuadPart
- TICKSTO1970
;
268 IntTime
.QuadPart
= IntTime
.QuadPart
/ TICKSPERSEC
;
270 if (IntTime
.u
.HighPart
!= 0)
273 *SecondsSince1970
= IntTime
.u
.LowPart
;
284 RtlTimeToSecondsSince1980(
286 PULONG SecondsSince1980
)
288 LARGE_INTEGER IntTime
;
290 IntTime
.QuadPart
= Time
->QuadPart
- TICKSTO1980
;
291 IntTime
.QuadPart
= IntTime
.QuadPart
/ TICKSPERSEC
;
293 if (IntTime
.u
.HighPart
!= 0)
296 *SecondsSince1980
= IntTime
.u
.LowPart
;
307 RtlLocalTimeToSystemTime(PLARGE_INTEGER LocalTime
,
308 PLARGE_INTEGER SystemTime
)
310 SYSTEM_TIMEOFDAY_INFORMATION TimeInformation
;
313 Status
= NtQuerySystemInformation(SystemTimeOfDayInformation
,
315 sizeof(SYSTEM_TIMEOFDAY_INFORMATION
),
317 if (!NT_SUCCESS(Status
))
320 SystemTime
->QuadPart
= LocalTime
->QuadPart
+
321 TimeInformation
.TimeZoneBias
.QuadPart
;
323 return(STATUS_SUCCESS
);
332 RtlSystemTimeToLocalTime(PLARGE_INTEGER SystemTime
,
333 PLARGE_INTEGER LocalTime
)
335 SYSTEM_TIMEOFDAY_INFORMATION TimeInformation
;
338 Status
= NtQuerySystemInformation(SystemTimeOfDayInformation
,
340 sizeof(SYSTEM_TIMEOFDAY_INFORMATION
),
342 if (!NT_SUCCESS(Status
))
345 LocalTime
->QuadPart
= SystemTime
->QuadPart
-
346 TimeInformation
.TimeZoneBias
.QuadPart
;
348 return(STATUS_SUCCESS
);
357 RtlSecondsSince1970ToTime(
358 ULONG SecondsSince1970
,
361 Time
->QuadPart
= ((LONGLONG
)SecondsSince1970
* TICKSPERSEC
) + TICKSTO1970
;
370 RtlSecondsSince1980ToTime(
371 ULONG SecondsSince1980
,
374 Time
->QuadPart
= ((LONGLONG
)SecondsSince1980
* TICKSPERSEC
) + TICKSTO1980
;