4 * Copyright (C) 2004-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.56 2008/02/15 23:46:51 tbox Exp */
31 #include <sys/time.h> /* Required for struct timeval on some platforms. */
34 #include <isc/print.h>
35 #include <isc/strerror.h>
36 #include <isc/string.h>
40 #define NS_PER_S 1000000000 /*%< Nanoseconds per second. */
41 #define NS_PER_US 1000 /*%< Nanoseconds per microsecond. */
42 #define US_PER_S 1000000 /*%< Microseconds per second. */
45 * All of the INSIST()s checks of nanoseconds < NS_PER_S are for
46 * consistency checking of the type. In lieu of magic numbers, it
47 * is the best we've got. The check is only performed on functions which
48 * need an initialized type.
51 #ifndef ISC_FIX_TV_USEC
52 #define ISC_FIX_TV_USEC 1
59 static isc_interval_t zero_interval
= { 0, 0 };
60 isc_interval_t
*isc_interval_zero
= &zero_interval
;
64 fix_tv_usec(struct timeval
*tv
) {
65 isc_boolean_t fixed
= ISC_FALSE
;
67 if (tv
->tv_usec
< 0) {
71 tv
->tv_usec
+= US_PER_S
;
72 } while (tv
->tv_usec
< 0);
73 } else if (tv
->tv_usec
>= US_PER_S
) {
77 tv
->tv_usec
-= US_PER_S
;
78 } while (tv
->tv_usec
>=US_PER_S
);
81 * Call syslog directly as was are called from the logging functions.
84 (void)syslog(LOG_ERR
, "gettimeofday returned bad tv_usec: corrected");
89 isc_interval_set(isc_interval_t
*i
,
90 unsigned int seconds
, unsigned int nanoseconds
)
93 REQUIRE(nanoseconds
< NS_PER_S
);
96 i
->nanoseconds
= nanoseconds
;
100 isc_interval_iszero(const isc_interval_t
*i
) {
102 INSIST(i
->nanoseconds
< NS_PER_S
);
104 if (i
->seconds
== 0 && i
->nanoseconds
== 0)
115 static isc_time_t epoch
= { 0, 0 };
116 isc_time_t
*isc_time_epoch
= &epoch
;
119 isc_time_set(isc_time_t
*t
, unsigned int seconds
, unsigned int nanoseconds
) {
121 REQUIRE(nanoseconds
< NS_PER_S
);
123 t
->seconds
= seconds
;
124 t
->nanoseconds
= nanoseconds
;
128 isc_time_settoepoch(isc_time_t
*t
) {
136 isc_time_isepoch(const isc_time_t
*t
) {
138 INSIST(t
->nanoseconds
< NS_PER_S
);
140 if (t
->seconds
== 0 && t
->nanoseconds
== 0)
148 isc_time_now(isc_time_t
*t
) {
150 char strbuf
[ISC_STRERRORSIZE
];
154 if (gettimeofday(&tv
, NULL
) == -1) {
155 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
156 UNEXPECTED_ERROR(__FILE__
, __LINE__
, "%s", strbuf
);
157 return (ISC_R_UNEXPECTED
);
161 * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not,
162 * then this test will generate warnings for platforms on which it is
163 * unsigned. In any event, the chances of any of these problems
164 * happening are pretty much zero, but since the libisc library ensures
165 * certain things to be true ...
170 return (ISC_R_UNEXPECTED
);
172 if (tv
.tv_sec
< 0 || tv
.tv_usec
< 0 || tv
.tv_usec
>= US_PER_S
)
173 return (ISC_R_UNEXPECTED
);
177 * Ensure the tv_sec value fits in t->seconds.
179 if (sizeof(tv
.tv_sec
) > sizeof(t
->seconds
) &&
180 ((tv
.tv_sec
| (unsigned int)-1) ^ (unsigned int)-1) != 0U)
181 return (ISC_R_RANGE
);
183 t
->seconds
= tv
.tv_sec
;
184 t
->nanoseconds
= tv
.tv_usec
* NS_PER_US
;
186 return (ISC_R_SUCCESS
);
190 isc_time_nowplusinterval(isc_time_t
*t
, const isc_interval_t
*i
) {
192 char strbuf
[ISC_STRERRORSIZE
];
196 INSIST(i
->nanoseconds
< NS_PER_S
);
198 if (gettimeofday(&tv
, NULL
) == -1) {
199 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
200 UNEXPECTED_ERROR(__FILE__
, __LINE__
, "%s", strbuf
);
201 return (ISC_R_UNEXPECTED
);
205 * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not,
206 * then this test will generate warnings for platforms on which it is
207 * unsigned. In any event, the chances of any of these problems
208 * happening are pretty much zero, but since the libisc library ensures
209 * certain things to be true ...
214 return (ISC_R_UNEXPECTED
);
216 if (tv
.tv_sec
< 0 || tv
.tv_usec
< 0 || tv
.tv_usec
>= US_PER_S
)
217 return (ISC_R_UNEXPECTED
);
221 * Ensure the resulting seconds value fits in the size of an
222 * unsigned int. (It is written this way as a slight optimization;
223 * note that even if both values == INT_MAX, then when added
224 * and getting another 1 added below the result is UINT_MAX.)
226 if ((tv
.tv_sec
> INT_MAX
|| i
->seconds
> INT_MAX
) &&
227 ((long long)tv
.tv_sec
+ i
->seconds
> UINT_MAX
))
228 return (ISC_R_RANGE
);
230 t
->seconds
= tv
.tv_sec
+ i
->seconds
;
231 t
->nanoseconds
= tv
.tv_usec
* NS_PER_US
+ i
->nanoseconds
;
232 if (t
->nanoseconds
>= NS_PER_S
) {
234 t
->nanoseconds
-= NS_PER_S
;
237 return (ISC_R_SUCCESS
);
241 isc_time_compare(const isc_time_t
*t1
, const isc_time_t
*t2
) {
242 REQUIRE(t1
!= NULL
&& t2
!= NULL
);
243 INSIST(t1
->nanoseconds
< NS_PER_S
&& t2
->nanoseconds
< NS_PER_S
);
245 if (t1
->seconds
< t2
->seconds
)
247 if (t1
->seconds
> t2
->seconds
)
249 if (t1
->nanoseconds
< t2
->nanoseconds
)
251 if (t1
->nanoseconds
> t2
->nanoseconds
)
257 isc_time_add(const isc_time_t
*t
, const isc_interval_t
*i
, isc_time_t
*result
)
259 REQUIRE(t
!= NULL
&& i
!= NULL
&& result
!= NULL
);
260 INSIST(t
->nanoseconds
< NS_PER_S
&& i
->nanoseconds
< NS_PER_S
);
263 * Ensure the resulting seconds value fits in the size of an
264 * unsigned int. (It is written this way as a slight optimization;
265 * note that even if both values == INT_MAX, then when added
266 * and getting another 1 added below the result is UINT_MAX.)
268 if ((t
->seconds
> INT_MAX
|| i
->seconds
> INT_MAX
) &&
269 ((long long)t
->seconds
+ i
->seconds
> UINT_MAX
))
270 return (ISC_R_RANGE
);
272 result
->seconds
= t
->seconds
+ i
->seconds
;
273 result
->nanoseconds
= t
->nanoseconds
+ i
->nanoseconds
;
274 if (result
->nanoseconds
>= NS_PER_S
) {
276 result
->nanoseconds
-= NS_PER_S
;
279 return (ISC_R_SUCCESS
);
283 isc_time_subtract(const isc_time_t
*t
, const isc_interval_t
*i
,
286 REQUIRE(t
!= NULL
&& i
!= NULL
&& result
!= NULL
);
287 INSIST(t
->nanoseconds
< NS_PER_S
&& i
->nanoseconds
< NS_PER_S
);
289 if ((unsigned int)t
->seconds
< i
->seconds
||
290 ((unsigned int)t
->seconds
== i
->seconds
&&
291 t
->nanoseconds
< i
->nanoseconds
))
292 return (ISC_R_RANGE
);
294 result
->seconds
= t
->seconds
- i
->seconds
;
295 if (t
->nanoseconds
>= i
->nanoseconds
)
296 result
->nanoseconds
= t
->nanoseconds
- i
->nanoseconds
;
298 result
->nanoseconds
= NS_PER_S
- i
->nanoseconds
+
303 return (ISC_R_SUCCESS
);
307 isc_time_microdiff(const isc_time_t
*t1
, const isc_time_t
*t2
) {
308 isc_uint64_t i1
, i2
, i3
;
310 REQUIRE(t1
!= NULL
&& t2
!= NULL
);
311 INSIST(t1
->nanoseconds
< NS_PER_S
&& t2
->nanoseconds
< NS_PER_S
);
313 i1
= (isc_uint64_t
)t1
->seconds
* NS_PER_S
+ t1
->nanoseconds
;
314 i2
= (isc_uint64_t
)t2
->seconds
* NS_PER_S
+ t2
->nanoseconds
;
322 * Convert to microseconds.
324 i3
= (i1
- i2
) / NS_PER_US
;
330 isc_time_seconds(const isc_time_t
*t
) {
332 INSIST(t
->nanoseconds
< NS_PER_S
);
334 return ((isc_uint32_t
)t
->seconds
);
338 isc_time_secondsastimet(const isc_time_t
*t
, time_t *secondsp
) {
343 INSIST(t
->nanoseconds
< NS_PER_S
);
346 * Ensure that the number of seconds represented by t->seconds
347 * can be represented by a time_t. Since t->seconds is an unsigned
348 * int and since time_t is mostly opaque, this is trickier than
349 * it seems. (This standardized opaqueness of time_t is *very*
350 * frustrating; time_t is not even limited to being an integral
353 * The mission, then, is to avoid generating any kind of warning
354 * about "signed versus unsigned" while trying to determine if the
355 * the unsigned int t->seconds is out range for tv_sec, which is
356 * pretty much only true if time_t is a signed integer of the same
357 * size as the return value of isc_time_seconds.
359 * The use of the 64 bit integer ``i'' takes advantage of C's
360 * conversion rules to either zero fill or sign extend the widened
363 * Solaris 5.6 gives this warning about the left shift:
364 * warning: integer overflow detected: op "<<"
365 * if the U(nsigned) qualifier is not on the 1.
367 seconds
= (time_t)t
->seconds
;
369 INSIST(sizeof(unsigned int) == sizeof(isc_uint32_t
));
370 INSIST(sizeof(time_t) >= sizeof(isc_uint32_t
));
372 if (sizeof(time_t) == sizeof(isc_uint32_t
) && /* Same size. */
373 (time_t)0.5 != 0.5 && /* Not a floating point type. */
374 (i
= (time_t)-1) != 4294967295u && /* Is signed. */
376 (1U << (sizeof(time_t) * CHAR_BIT
- 1))) != 0U) { /* Negative. */
378 * This UNUSED() is here to shut up the IRIX compiler:
379 * variable "i" was set but never used
380 * when the value of i *was* used in the third test.
381 * (Let's hope the compiler got the actual test right.)
384 return (ISC_R_RANGE
);
389 return (ISC_R_SUCCESS
);
393 isc_time_nanoseconds(const isc_time_t
*t
) {
396 ENSURE(t
->nanoseconds
< NS_PER_S
);
398 return ((isc_uint32_t
)t
->nanoseconds
);
402 isc_time_formattimestamp(const isc_time_t
*t
, char *buf
, unsigned int len
) {
408 now
= (time_t) t
->seconds
;
409 flen
= strftime(buf
, len
, "%d-%b-%Y %X", localtime(&now
));
412 snprintf(buf
+ flen
, len
- flen
,
413 ".%03u", t
->nanoseconds
/ 1000000);
415 snprintf(buf
, len
, "99-Bad-9999 99:99:99.999");
419 isc_time_formathttptimestamp(const isc_time_t
*t
, char *buf
, unsigned int len
) {
425 now
= (time_t)t
->seconds
;
426 flen
= strftime(buf
, len
, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now
));
431 isc_time_formatISO8601(const isc_time_t
*t
, char *buf
, unsigned int len
) {
437 now
= (time_t)t
->seconds
;
438 flen
= strftime(buf
, len
, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now
));