4 * Copyright (C) 2004, 2006-2008 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.48 2008/09/08 23:47:10 tbox 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
) {
234 * Convert the time to a SYSTEMTIME structure and the grab the
237 FileTimeToSystemTime(&t
->absolute
, &st
);
239 return ((isc_uint32_t
)(st
.wMilliseconds
/ 1000));
243 isc_time_nanoseconds(const isc_time_t
*t
) {
247 * Convert the time to a SYSTEMTIME structure and the grab the
250 FileTimeToSystemTime(&t
->absolute
, &st
);
252 return ((isc_uint32_t
)(st
.wMilliseconds
* 1000000));
256 isc_time_formattimestamp(const isc_time_t
*t
, char *buf
, unsigned int len
) {
262 static const char badtime
[] = "99-Bad-9999 99:99:99.999";
265 if (FileTimeToLocalFileTime(&t
->absolute
, &localft
) &&
266 FileTimeToSystemTime(&localft
, &st
)) {
267 GetDateFormat(LOCALE_USER_DEFAULT
, 0, &st
, "dd-MMM-yyyy",
269 GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOTIMEMARKER
|
270 TIME_FORCE24HOURFORMAT
, &st
, NULL
, TimeBuf
, 50);
272 snprintf(buf
, len
, "%s %s.%03u", DateBuf
, TimeBuf
,
276 snprintf(buf
, len
, badtime
);
280 isc_time_formathttptimestamp(const isc_time_t
*t
, char *buf
, unsigned int len
) {
286 if (FileTimeToSystemTime(&t
->absolute
, &st
)) {
287 GetDateFormat(LOCALE_USER_DEFAULT
, 0, &st
, "ddd',', dd-MMM-yyyy",
289 GetTimeFormat(LOCALE_USER_DEFAULT
,
290 TIME_NOTIMEMARKER
| TIME_FORCE24HOURFORMAT
,
291 &st
, "hh':'mm':'ss", TimeBuf
, 50);
293 snprintf(buf
, len
, "%s %s GMT", DateBuf
, TimeBuf
);