4 * Copyright (C) 2004, 2006-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1998-2001, 2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: time.c,v 1.52 2009/08/14 07:51:08 marka Exp */
33 #include <isc/assertions.h>
38 * struct FILETIME uses "100-nanoseconds intervals".
39 * NS / S = 1000000000 (10^9).
40 * While it is reasonably obvious that this makes the needed
41 * conversion factor 10^7, it is coded this way for additional clarity.
43 #define NS_PER_S 1000000000
44 #define NS_INTERVAL 100
45 #define INTERVALS_PER_S (NS_PER_S / NS_INTERVAL)
46 #define UINT64_MAX _UI64_MAX
52 static isc_time_t epoch
= { { 0, 0 } };
53 LIBISC_EXTERNAL_DATA isc_time_t
*isc_time_epoch
= &epoch
;
59 static isc_interval_t zero_interval
= { 0 };
60 LIBISC_EXTERNAL_DATA isc_interval_t
*isc_interval_zero
= &zero_interval
;
63 isc_interval_set(isc_interval_t
*i
, unsigned int seconds
,
64 unsigned int nanoseconds
)
67 REQUIRE(nanoseconds
< NS_PER_S
);
70 * This rounds nanoseconds up not down.
72 i
->interval
= (LONGLONG
)seconds
* INTERVALS_PER_S
73 + (nanoseconds
+ NS_INTERVAL
- 1) / NS_INTERVAL
;
77 isc_interval_iszero(const isc_interval_t
*i
) {
86 isc_time_set(isc_time_t
*t
, unsigned int seconds
, unsigned int nanoseconds
) {
87 SYSTEMTIME epoch
= { 1970, 1, 4, 1, 0, 0, 0, 0 };
92 REQUIRE(nanoseconds
< NS_PER_S
);
94 SystemTimeToFileTime(&epoch
, &temp
);
96 i1
.LowPart
= t
->absolute
.dwLowDateTime
;
97 i1
.HighPart
= t
->absolute
.dwHighDateTime
;
99 i1
.QuadPart
+= (unsigned __int64
)nanoseconds
/100;
100 i1
.QuadPart
+= (unsigned __int64
)seconds
*10000000;
102 t
->absolute
.dwLowDateTime
= i1
.LowPart
;
103 t
->absolute
.dwHighDateTime
= i1
.HighPart
;
107 isc_time_settoepoch(isc_time_t
*t
) {
110 t
->absolute
.dwLowDateTime
= 0;
111 t
->absolute
.dwHighDateTime
= 0;
115 isc_time_isepoch(const isc_time_t
*t
) {
118 if (t
->absolute
.dwLowDateTime
== 0 &&
119 t
->absolute
.dwHighDateTime
== 0)
126 isc_time_now(isc_time_t
*t
) {
129 GetSystemTimeAsFileTime(&t
->absolute
);
131 return (ISC_R_SUCCESS
);
135 isc_time_nowplusinterval(isc_time_t
*t
, const isc_interval_t
*i
) {
141 GetSystemTimeAsFileTime(&t
->absolute
);
143 i1
.LowPart
= t
->absolute
.dwLowDateTime
;
144 i1
.HighPart
= t
->absolute
.dwHighDateTime
;
146 if (UINT64_MAX
- i1
.QuadPart
< (unsigned __int64
)i
->interval
)
147 return (ISC_R_RANGE
);
149 i1
.QuadPart
+= i
->interval
;
151 t
->absolute
.dwLowDateTime
= i1
.LowPart
;
152 t
->absolute
.dwHighDateTime
= i1
.HighPart
;
154 return (ISC_R_SUCCESS
);
158 isc_time_compare(const isc_time_t
*t1
, const isc_time_t
*t2
) {
159 REQUIRE(t1
!= NULL
&& t2
!= NULL
);
161 return ((int)CompareFileTime(&t1
->absolute
, &t2
->absolute
));
165 isc_time_add(const isc_time_t
*t
, const isc_interval_t
*i
, isc_time_t
*result
)
169 REQUIRE(t
!= NULL
&& i
!= NULL
&& result
!= NULL
);
171 i1
.LowPart
= t
->absolute
.dwLowDateTime
;
172 i1
.HighPart
= t
->absolute
.dwHighDateTime
;
174 if (UINT64_MAX
- i1
.QuadPart
< (unsigned __int64
)i
->interval
)
175 return (ISC_R_RANGE
);
177 i1
.QuadPart
+= i
->interval
;
179 result
->absolute
.dwLowDateTime
= i1
.LowPart
;
180 result
->absolute
.dwHighDateTime
= i1
.HighPart
;
182 return (ISC_R_SUCCESS
);
186 isc_time_subtract(const isc_time_t
*t
, const isc_interval_t
*i
,
187 isc_time_t
*result
) {
190 REQUIRE(t
!= NULL
&& i
!= NULL
&& result
!= NULL
);
192 i1
.LowPart
= t
->absolute
.dwLowDateTime
;
193 i1
.HighPart
= t
->absolute
.dwHighDateTime
;
195 if (i1
.QuadPart
< (unsigned __int64
) i
->interval
)
196 return (ISC_R_RANGE
);
198 i1
.QuadPart
-= i
->interval
;
200 result
->absolute
.dwLowDateTime
= i1
.LowPart
;
201 result
->absolute
.dwHighDateTime
= i1
.HighPart
;
203 return (ISC_R_SUCCESS
);
207 isc_time_microdiff(const isc_time_t
*t1
, const isc_time_t
*t2
) {
208 ULARGE_INTEGER i1
, i2
;
211 REQUIRE(t1
!= NULL
&& t2
!= NULL
);
213 i1
.LowPart
= t1
->absolute
.dwLowDateTime
;
214 i1
.HighPart
= t1
->absolute
.dwHighDateTime
;
215 i2
.LowPart
= t2
->absolute
.dwLowDateTime
;
216 i2
.HighPart
= t2
->absolute
.dwHighDateTime
;
218 if (i1
.QuadPart
<= i2
.QuadPart
)
222 * Convert to microseconds.
224 i3
= (i1
.QuadPart
- i2
.QuadPart
) / 10;
230 isc_time_seconds(const isc_time_t
*t
) {
231 SYSTEMTIME epoch
= { 1970, 1, 4, 1, 0, 0, 0, 0 };
233 ULARGE_INTEGER i1
, i2
;
236 SystemTimeToFileTime(&epoch
, &temp
);
238 i1
.LowPart
= t
->absolute
.dwLowDateTime
;
239 i1
.HighPart
= t
->absolute
.dwHighDateTime
;
240 i2
.LowPart
= temp
.dwLowDateTime
;
241 i2
.HighPart
= temp
.dwHighDateTime
;
243 i3
= (i1
.QuadPart
- i2
.QuadPart
) / 10000000;
245 return ((isc_uint32_t
)i3
);
249 isc_time_nanoseconds(const isc_time_t
*t
) {
252 i
.LowPart
= t
->absolute
.dwLowDateTime
;
253 i
.HighPart
= t
->absolute
.dwHighDateTime
;
254 return ((isc_uint32_t
)(i
.QuadPart
% 10000000) * 100);
258 isc_time_formattimestamp(const isc_time_t
*t
, char *buf
, unsigned int len
) {
264 static const char badtime
[] = "99-Bad-9999 99:99:99.999";
267 if (FileTimeToLocalFileTime(&t
->absolute
, &localft
) &&
268 FileTimeToSystemTime(&localft
, &st
)) {
269 GetDateFormat(LOCALE_USER_DEFAULT
, 0, &st
, "dd-MMM-yyyy",
271 GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOTIMEMARKER
|
272 TIME_FORCE24HOURFORMAT
, &st
, NULL
, TimeBuf
, 50);
274 snprintf(buf
, len
, "%s %s.%03u", DateBuf
, TimeBuf
,
278 snprintf(buf
, len
, badtime
);
282 isc_time_formathttptimestamp(const isc_time_t
*t
, char *buf
, unsigned int len
) {
287 /* strftime() format: "%a, %d %b %Y %H:%M:%S GMT" */
290 if (FileTimeToSystemTime(&t
->absolute
, &st
)) {
291 GetDateFormat(LOCALE_USER_DEFAULT
, 0, &st
,
292 "ddd',', dd-MMM-yyyy", DateBuf
, 50);
293 GetTimeFormat(LOCALE_USER_DEFAULT
,
294 TIME_NOTIMEMARKER
| TIME_FORCE24HOURFORMAT
,
295 &st
, "hh':'mm':'ss", TimeBuf
, 50);
297 snprintf(buf
, len
, "%s %s GMT", DateBuf
, TimeBuf
);
304 isc_time_formatISO8601(const isc_time_t
*t
, char *buf
, unsigned int len
) {
309 /* strtime() format: "%Y-%m-%dT%H:%M:%SZ" */
312 if (FileTimeToSystemTime(&t
->absolute
, &st
)) {
313 GetDateFormat(LOCALE_NEUTRAL
, 0, &st
, "yyyy-MM-dd",
315 GetTimeFormat(LOCALE_NEUTRAL
,
316 TIME_NOTIMEMARKER
| TIME_FORCE24HOURFORMAT
,
317 &st
, "hh':'mm':'ss", TimeBuf
, 50);
318 snprintf(buf
, len
, "%s%sZ", DateBuf
, TimeBuf
);