2 * Conversion between Time and TimeFields
4 * RtlTimeToTimeFields, RtlTimeFieldsToTime and defines are taken from ReactOS and
5 * adapted to wine with special permissions of the author
6 * Rex Jolliff (rex@lvcablemodem.com)
8 * Copyright 1999 Juergen Schmied
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #ifdef HAVE_SYS_TIME_H
30 # include <sys/time.h>
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ntdll
);
40 #define TICKSPERSEC 10000000
41 #define TICKSPERMSEC 10000
42 #define SECSPERDAY 86400
43 #define SECSPERHOUR 3600
45 #define MINSPERHOUR 60
46 #define HOURSPERDAY 24
47 #define EPOCHWEEKDAY 0
49 #define EPOCHYEAR 1601
50 #define DAYSPERNORMALYEAR 365
51 #define DAYSPERLEAPYEAR 366
52 #define MONSPERYEAR 12
54 /* 1601 to 1970 is 369 years plus 89 leap days */
55 #define SECS_1601_TO_1970 ((369 * 365 + 89) * 86400ULL)
56 /* 1601 to 1980 is 379 years plus 91 leap days */
57 #define SECS_1601_to_1980 ((379 * 365 + 91) * 86400ULL)
60 static const int YearLengths
[2] = {DAYSPERNORMALYEAR
, DAYSPERLEAPYEAR
};
61 static const int MonthLengths
[2][MONSPERYEAR
] =
63 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
64 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
67 static inline int IsLeapYear(int Year
)
69 return Year
% 4 == 0 && (Year
% 100 != 0 || Year
% 400 == 0) ? 1 : 0;
72 static inline void NormalizeTimeFields(CSHORT
*FieldToNormalize
, CSHORT
*CarryField
,int Modulus
)
74 *FieldToNormalize
= (CSHORT
) (*FieldToNormalize
- Modulus
);
75 *CarryField
= (CSHORT
) (*CarryField
+ 1);
78 /******************************************************************************
79 * RtlTimeToTimeFields [NTDLL.@]
83 VOID WINAPI
RtlTimeToTimeFields(
84 PLARGE_INTEGER liTime
,
85 PTIME_FIELDS TimeFields
)
88 int LeapSecondCorrections
, SecondsInDay
, CurYear
;
89 int LeapYear
, CurMonth
, GMTOffset
;
91 long long int Time
= *(long long int *)&liTime
;
93 /* Extract millisecond from time and convert time into seconds */
94 TimeFields
->Milliseconds
= (CSHORT
) ((Time
% TICKSPERSEC
) / TICKSPERMSEC
);
95 Time
= Time
/ TICKSPERSEC
;
97 /* FIXME: Compute the number of leap second corrections here */
98 LeapSecondCorrections
= 0;
100 /* FIXME: get the GMT offset here */
103 /* Split the time into days and seconds within the day */
104 Days
= Time
/ SECSPERDAY
;
105 SecondsInDay
= Time
% SECSPERDAY
;
107 /* Adjust the values for GMT and leap seconds */
108 SecondsInDay
+= (GMTOffset
- LeapSecondCorrections
);
109 while (SecondsInDay
< 0)
110 { SecondsInDay
+= SECSPERDAY
;
113 while (SecondsInDay
>= SECSPERDAY
)
114 { SecondsInDay
-= SECSPERDAY
;
118 /* compute time of day */
119 TimeFields
->Hour
= (CSHORT
) (SecondsInDay
/ SECSPERHOUR
);
120 SecondsInDay
= SecondsInDay
% SECSPERHOUR
;
121 TimeFields
->Minute
= (CSHORT
) (SecondsInDay
/ SECSPERMIN
);
122 TimeFields
->Second
= (CSHORT
) (SecondsInDay
% SECSPERMIN
);
124 /* FIXME: handle the possibility that we are on a leap second (i.e. Second = 60) */
126 /* compute day of week */
127 TimeFields
->Weekday
= (CSHORT
) ((EPOCHWEEKDAY
+ Days
) % DAYSPERWEEK
);
131 /* FIXME: handle calendar modifications */
133 { LeapYear
= IsLeapYear(CurYear
);
134 if (Days
< (long) YearLengths
[LeapYear
])
138 Days
= Days
- (long) YearLengths
[LeapYear
];
140 TimeFields
->Year
= (CSHORT
) CurYear
;
142 /* Compute month of year */
143 Months
= MonthLengths
[LeapYear
];
144 for (CurMonth
= 0; Days
>= (long) Months
[CurMonth
]; CurMonth
++)
145 Days
= Days
- (long) Months
[CurMonth
];
146 TimeFields
->Month
= (CSHORT
) (CurMonth
+ 1);
147 TimeFields
->Day
= (CSHORT
) (Days
+ 1);
149 /******************************************************************************
150 * RtlTimeFieldsToTime [NTDLL.@]
153 BOOLEAN WINAPI
RtlTimeFieldsToTime(
154 PTIME_FIELDS tfTimeFields
,
157 int CurYear
, CurMonth
;
158 long long int rcTime
;
159 TIME_FIELDS TimeFields
= *tfTimeFields
;
163 /* FIXME: normalize the TIME_FIELDS structure here */
164 while (TimeFields
.Second
>= SECSPERMIN
)
165 { NormalizeTimeFields(&TimeFields
.Second
, &TimeFields
.Minute
, SECSPERMIN
);
167 while (TimeFields
.Minute
>= MINSPERHOUR
)
168 { NormalizeTimeFields(&TimeFields
.Minute
, &TimeFields
.Hour
, MINSPERHOUR
);
170 while (TimeFields
.Hour
>= HOURSPERDAY
)
171 { NormalizeTimeFields(&TimeFields
.Hour
, &TimeFields
.Day
, HOURSPERDAY
);
173 while (TimeFields
.Day
> MonthLengths
[IsLeapYear(TimeFields
.Year
)][TimeFields
.Month
- 1])
174 { NormalizeTimeFields(&TimeFields
.Day
, &TimeFields
.Month
, SECSPERMIN
);
176 while (TimeFields
.Month
> MONSPERYEAR
)
177 { NormalizeTimeFields(&TimeFields
.Month
, &TimeFields
.Year
, MONSPERYEAR
);
180 /* FIXME: handle calendar corrections here */
181 for (CurYear
= EPOCHYEAR
; CurYear
< TimeFields
.Year
; CurYear
++)
182 { rcTime
+= YearLengths
[IsLeapYear(CurYear
)];
184 for (CurMonth
= 1; CurMonth
< TimeFields
.Month
; CurMonth
++)
185 { rcTime
+= MonthLengths
[IsLeapYear(CurYear
)][CurMonth
- 1];
187 rcTime
+= TimeFields
.Day
- 1;
188 rcTime
*= SECSPERDAY
;
189 rcTime
+= TimeFields
.Hour
* SECSPERHOUR
+ TimeFields
.Minute
* SECSPERMIN
+ TimeFields
.Second
;
190 rcTime
*= TICKSPERSEC
;
191 rcTime
+= TimeFields
.Milliseconds
* TICKSPERMSEC
;
192 *Time
= *(LARGE_INTEGER
*)&rcTime
;
196 /************* end of code by Rex Jolliff (rex@lvcablemodem.com) *******************/
198 /******************************************************************************
199 * RtlSystemTimeToLocalTime [NTDLL.@]
201 VOID WINAPI
RtlSystemTimeToLocalTime(
202 IN PLARGE_INTEGER SystemTime
,
203 OUT PLARGE_INTEGER LocalTime
)
205 FIXME("(%p, %p),stub!\n",SystemTime
,LocalTime
);
207 memcpy (LocalTime
, SystemTime
, sizeof (PLARGE_INTEGER
));
210 /******************************************************************************
211 * RtlTimeToSecondsSince1970 [NTDLL.@]
213 BOOLEAN WINAPI
RtlTimeToSecondsSince1970( const FILETIME
*time
, LPDWORD res
)
215 ULONGLONG tmp
= ((ULONGLONG
)time
->dwHighDateTime
<< 32) | time
->dwLowDateTime
;
216 tmp
= RtlLargeIntegerDivide( tmp
, 10000000LL, NULL
);
217 tmp
-= SECS_1601_TO_1970
;
218 if (tmp
> 0xffffffff) return FALSE
;
223 /******************************************************************************
224 * RtlTimeToSecondsSince1980 [NTDLL.@]
226 BOOLEAN WINAPI
RtlTimeToSecondsSince1980( const FILETIME
*time
, LPDWORD res
)
228 ULONGLONG tmp
= ((ULONGLONG
)time
->dwHighDateTime
<< 32) | time
->dwLowDateTime
;
229 tmp
= RtlLargeIntegerDivide( tmp
, 10000000LL, NULL
);
230 tmp
-= SECS_1601_to_1980
;
231 if (tmp
> 0xffffffff) return FALSE
;
236 /******************************************************************************
237 * RtlSecondsSince1970ToTime [NTDLL.@]
239 void WINAPI
RtlSecondsSince1970ToTime( DWORD time
, FILETIME
*res
)
241 ULONGLONG secs
= RtlExtendedIntegerMultiply( time
+ SECS_1601_TO_1970
, 10000000 );
242 res
->dwLowDateTime
= (DWORD
)secs
;
243 res
->dwHighDateTime
= (DWORD
)(secs
>> 32);
246 /******************************************************************************
247 * RtlSecondsSince1980ToTime [NTDLL.@]
249 void WINAPI
RtlSecondsSince1980ToTime( DWORD time
, FILETIME
*res
)
251 ULONGLONG secs
= RtlExtendedIntegerMultiply( time
+ SECS_1601_to_1980
, 10000000 );
252 res
->dwLowDateTime
= (DWORD
)secs
;
253 res
->dwHighDateTime
= (DWORD
)(secs
>> 32);
256 /******************************************************************************
257 * RtlTimeToElapsedTimeFields [NTDLL.@]
258 * FIXME: prototype guessed
260 VOID WINAPI
RtlTimeToElapsedTimeFields(
261 PLARGE_INTEGER liTime
,
262 PTIME_FIELDS TimeFields
)
264 FIXME("(%p,%p): stub\n",liTime
,TimeFields
);
267 /***********************************************************************
268 * NtQuerySystemTime (NTDLL.@)
269 * ZwQuerySystemTime (NTDLL.@)
271 void WINAPI
NtQuerySystemTime( LARGE_INTEGER
*time
)
276 gettimeofday( &now
, 0 );
277 secs
= RtlExtendedIntegerMultiply( now
.tv_sec
+SECS_1601_TO_1970
, 10000000 ) + now
.tv_usec
* 10;
278 time
->s
.LowPart
= (DWORD
)secs
;
279 time
->s
.HighPart
= (DWORD
)(secs
>> 32);