1 /* $Id: time.c,v 1.5 2000/04/07 12:45:22 ekohl Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: lib/ntdll/rtl/time.c
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>
18 #include <internal/debug.h>
20 #define TICKSPERSEC 10000000
21 #define TICKSPERMSEC 10000
22 #define SECSPERDAY 86400
23 #define SECSPERHOUR 3600
25 #define MINSPERHOUR 60
26 #define HOURSPERDAY 24
27 #define EPOCHWEEKDAY 0
29 #define EPOCHYEAR 1601
30 #define DAYSPERNORMALYEAR 365
31 #define DAYSPERLEAPYEAR 366
32 #define MONSPERYEAR 12
34 #define TICKSTO1970 0x019db1ded53e8000
35 #define TICKSTO1980 0x01a8e79fe1d58000
37 static const int YearLengths
[2] = {DAYSPERNORMALYEAR
, DAYSPERLEAPYEAR
};
38 static const int MonthLengths
[2][MONSPERYEAR
] =
40 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
41 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
44 static __inline
int IsLeapYear(int Year
)
46 return Year
% 4 == 0 && (Year
% 100 != 0 || Year
% 400 == 0) ? 1 : 0;
49 static __inline
void NormalizeTimeFields(CSHORT
*FieldToNormalize
,
53 *FieldToNormalize
= (CSHORT
) (*FieldToNormalize
- Modulus
);
54 *CarryField
= (CSHORT
) (*CarryField
+ 1);
57 /* FUNCTIONS *****************************************************************/
62 PLARGE_INTEGER liTime
,
63 PTIME_FIELDS TimeFields
67 int LeapSecondCorrections
, SecondsInDay
, CurYear
;
68 int LeapYear
, CurMonth
, GMTOffset
;
70 long long int Time
= (long long int)liTime
->QuadPart
;
72 /* Extract millisecond from time and convert time into seconds */
73 TimeFields
->Milliseconds
= (CSHORT
) ((Time
% TICKSPERSEC
) / TICKSPERMSEC
);
74 Time
= Time
/ TICKSPERSEC
;
76 /* FIXME: Compute the number of leap second corrections here */
77 LeapSecondCorrections
= 0;
79 /* FIXME: get the GMT offset here */
82 /* Split the time into days and seconds within the day */
83 Days
= Time
/ SECSPERDAY
;
84 SecondsInDay
= Time
% SECSPERDAY
;
86 /* Adjust the values for GMT and leap seconds */
87 SecondsInDay
+= (GMTOffset
- LeapSecondCorrections
);
88 while (SecondsInDay
< 0)
90 SecondsInDay
+= SECSPERDAY
;
93 while (SecondsInDay
>= SECSPERDAY
)
95 SecondsInDay
-= SECSPERDAY
;
99 /* compute time of day */
100 TimeFields
->Hour
= (CSHORT
) (SecondsInDay
/ SECSPERHOUR
);
101 SecondsInDay
= SecondsInDay
% SECSPERHOUR
;
102 TimeFields
->Minute
= (CSHORT
) (SecondsInDay
/ SECSPERMIN
);
103 TimeFields
->Second
= (CSHORT
) (SecondsInDay
% SECSPERMIN
);
105 /* FIXME: handle the possibility that we are on a leap second (i.e. Second = 60) */
107 /* compute day of week */
108 TimeFields
->Weekday
= (CSHORT
) ((EPOCHWEEKDAY
+ Days
) % DAYSPERWEEK
);
112 /* FIXME: handle calendar modifications */
115 LeapYear
= IsLeapYear(CurYear
);
116 if (Days
< (long) YearLengths
[LeapYear
])
121 Days
= Days
- (long) YearLengths
[LeapYear
];
123 TimeFields
->Year
= (CSHORT
) CurYear
;
125 /* Compute month of year */
126 Months
= MonthLengths
[LeapYear
];
127 for (CurMonth
= 0; Days
>= (long) Months
[CurMonth
]; CurMonth
++)
128 Days
= Days
- (long) Months
[CurMonth
];
129 TimeFields
->Month
= (CSHORT
) (CurMonth
+ 1);
130 TimeFields
->Day
= (CSHORT
) (Days
+ 1);
135 RtlTimeFieldsToTime (
136 PTIME_FIELDS tfTimeFields
,
140 int CurYear
, CurMonth
;
141 long long int rcTime
;
142 TIME_FIELDS TimeFields
= *tfTimeFields
;
146 /* FIXME: normalize the TIME_FIELDS structure here */
147 while (TimeFields
.Second
>= SECSPERMIN
)
149 NormalizeTimeFields(&TimeFields
.Second
,
153 while (TimeFields
.Minute
>= MINSPERHOUR
)
155 NormalizeTimeFields(&TimeFields
.Minute
,
159 while (TimeFields
.Hour
>= HOURSPERDAY
)
161 NormalizeTimeFields(&TimeFields
.Hour
,
165 while (TimeFields
.Day
>
166 MonthLengths
[IsLeapYear(TimeFields
.Year
)][TimeFields
.Month
- 1])
168 NormalizeTimeFields(&TimeFields
.Day
,
172 while (TimeFields
.Month
> MONSPERYEAR
)
174 NormalizeTimeFields(&TimeFields
.Month
,
179 /* FIXME: handle calendar corrections here */
180 for (CurYear
= EPOCHYEAR
; CurYear
< TimeFields
.Year
; CurYear
++)
182 rcTime
+= YearLengths
[IsLeapYear(CurYear
)];
184 for (CurMonth
= 1; CurMonth
< TimeFields
.Month
; CurMonth
++)
186 rcTime
+= MonthLengths
[IsLeapYear(CurYear
)][CurMonth
- 1];
188 rcTime
+= TimeFields
.Day
- 1;
189 rcTime
*= SECSPERDAY
;
190 rcTime
+= TimeFields
.Hour
* SECSPERHOUR
+ TimeFields
.Minute
* SECSPERMIN
+
192 rcTime
*= TICKSPERSEC
;
193 rcTime
+= TimeFields
.Milliseconds
* TICKSPERMSEC
;
194 *Time
= *(LARGE_INTEGER
*)&rcTime
;
202 RtlSecondsSince1970ToTime (
203 ULONG SecondsSince1970
,
209 llTime
= (SecondsSince1970
* TICKSPERSEC
) + TICKSTO1970
;
211 *Time
= *(LARGE_INTEGER
*)&llTime
;
217 RtlSecondsSince1980ToTime (
218 ULONG SecondsSince1980
,
224 llTime
= (SecondsSince1980
* TICKSPERSEC
) + TICKSTO1980
;
226 *Time
= *(LARGE_INTEGER
*)&llTime
;
232 RtlTimeToSecondsSince1970 (
234 PULONG SecondsSince1970
237 LARGE_INTEGER liTime
;
239 liTime
.QuadPart
= Time
->QuadPart
- TICKSTO1970
;
240 liTime
.QuadPart
= liTime
.QuadPart
/ TICKSPERSEC
;
242 if (liTime
.u
.HighPart
!= 0)
245 *SecondsSince1970
= liTime
.u
.LowPart
;
253 RtlTimeToSecondsSince1980 (
255 PULONG SecondsSince1980
258 LARGE_INTEGER liTime
;
260 liTime
.QuadPart
= Time
->QuadPart
- TICKSTO1980
;
261 liTime
.QuadPart
= liTime
.QuadPart
/ TICKSPERSEC
;
263 if (liTime
.u
.HighPart
!= 0)
266 *SecondsSince1980
= liTime
.u
.LowPart
;
274 RtlLocalTimeToSystemTime (
275 PLARGE_INTEGER LocalTime
,
276 PLARGE_INTEGER SystemTime
279 SYSTEM_TIME_INFORMATION TimeInformation
;
282 Status
= NtQuerySystemInformation (SystemTimeInformation
,
284 sizeof(SYSTEM_TIME_INFORMATION
),
286 if (!NT_SUCCESS(Status
))
289 SystemTime
->QuadPart
= LocalTime
->QuadPart
+
290 TimeInformation
.TimeZoneBias
.QuadPart
;
292 return STATUS_SUCCESS
;
298 RtlSystemTimeToLocalTime (
299 PLARGE_INTEGER SystemTime
,
300 PLARGE_INTEGER LocalTime
303 SYSTEM_TIME_INFORMATION TimeInformation
;
306 Status
= NtQuerySystemInformation (SystemTimeInformation
,
308 sizeof(SYSTEM_TIME_INFORMATION
),
310 if (!NT_SUCCESS(Status
))
313 LocalTime
->QuadPart
= SystemTime
->QuadPart
-
314 TimeInformation
.TimeZoneBias
.QuadPart
;
316 return STATUS_SUCCESS
;