2 * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1998-2001, 2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: time.c,v 1.54.128.2 2008/02/18 23:46:30 tbox Exp $ */
29 #include <sys/time.h> /* Required for struct timeval on some platforms. */
32 #include <isc/print.h>
33 #include <isc/strerror.h>
34 #include <isc/string.h>
38 #define NS_PER_S 1000000000 /*%< Nanoseconds per second. */
39 #define NS_PER_US 1000 /*%< Nanoseconds per microsecond. */
40 #define US_PER_S 1000000 /*%< Microseconds per second. */
43 * All of the INSIST()s checks of nanoseconds < NS_PER_S are for
44 * consistency checking of the type. In lieu of magic numbers, it
45 * is the best we've got. The check is only performed on functions which
46 * need an initialized type.
49 #ifndef ISC_FIX_TV_USEC
50 #define ISC_FIX_TV_USEC 1
57 static isc_interval_t zero_interval
= { 0, 0 };
58 isc_interval_t
*isc_interval_zero
= &zero_interval
;
62 fix_tv_usec(struct timeval
*tv
) {
63 isc_boolean_t fixed
= ISC_FALSE
;
65 if (tv
->tv_usec
< 0) {
69 tv
->tv_usec
+= US_PER_S
;
70 } while (tv
->tv_usec
< 0);
71 } else if (tv
->tv_usec
>= US_PER_S
) {
75 tv
->tv_usec
-= US_PER_S
;
76 } while (tv
->tv_usec
>=US_PER_S
);
79 * Call syslog directly as was are called from the logging functions.
82 (void)syslog(LOG_ERR
, "gettimeofday returned bad tv_usec: corrected");
87 isc_interval_set(isc_interval_t
*i
,
88 unsigned int seconds
, unsigned int nanoseconds
)
91 REQUIRE(nanoseconds
< NS_PER_S
);
94 i
->nanoseconds
= nanoseconds
;
98 isc_interval_iszero(const isc_interval_t
*i
) {
100 INSIST(i
->nanoseconds
< NS_PER_S
);
102 if (i
->seconds
== 0 && i
->nanoseconds
== 0)
113 static isc_time_t epoch
= { 0, 0 };
114 isc_time_t
*isc_time_epoch
= &epoch
;
117 isc_time_set(isc_time_t
*t
, unsigned int seconds
, unsigned int nanoseconds
) {
119 REQUIRE(nanoseconds
< NS_PER_S
);
121 t
->seconds
= seconds
;
122 t
->nanoseconds
= nanoseconds
;
126 isc_time_settoepoch(isc_time_t
*t
) {
134 isc_time_isepoch(const isc_time_t
*t
) {
136 INSIST(t
->nanoseconds
< NS_PER_S
);
138 if (t
->seconds
== 0 && t
->nanoseconds
== 0)
146 isc_time_now(isc_time_t
*t
) {
148 char strbuf
[ISC_STRERRORSIZE
];
152 if (gettimeofday(&tv
, NULL
) == -1) {
153 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
154 UNEXPECTED_ERROR(__FILE__
, __LINE__
, "%s", strbuf
);
155 return (ISC_R_UNEXPECTED
);
159 * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not,
160 * then this test will generate warnings for platforms on which it is
161 * unsigned. In any event, the chances of any of these problems
162 * happening are pretty much zero, but since the libisc library ensures
163 * certain things to be true ...
168 return (ISC_R_UNEXPECTED
);
170 if (tv
.tv_sec
< 0 || tv
.tv_usec
< 0 || tv
.tv_usec
>= US_PER_S
)
171 return (ISC_R_UNEXPECTED
);
175 * Ensure the tv_sec value fits in t->seconds.
177 if (sizeof(tv
.tv_sec
) > sizeof(t
->seconds
) &&
178 ((tv
.tv_sec
| (unsigned int)-1) ^ (unsigned int)-1) != 0U)
179 return (ISC_R_RANGE
);
181 t
->seconds
= tv
.tv_sec
;
182 t
->nanoseconds
= tv
.tv_usec
* NS_PER_US
;
184 return (ISC_R_SUCCESS
);
188 isc_time_nowplusinterval(isc_time_t
*t
, const isc_interval_t
*i
) {
190 char strbuf
[ISC_STRERRORSIZE
];
194 INSIST(i
->nanoseconds
< NS_PER_S
);
196 if (gettimeofday(&tv
, NULL
) == -1) {
197 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
198 UNEXPECTED_ERROR(__FILE__
, __LINE__
, "%s", strbuf
);
199 return (ISC_R_UNEXPECTED
);
203 * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not,
204 * then this test will generate warnings for platforms on which it is
205 * unsigned. In any event, the chances of any of these problems
206 * happening are pretty much zero, but since the libisc library ensures
207 * certain things to be true ...
212 return (ISC_R_UNEXPECTED
);
214 if (tv
.tv_sec
< 0 || tv
.tv_usec
< 0 || tv
.tv_usec
>= US_PER_S
)
215 return (ISC_R_UNEXPECTED
);
219 * Ensure the resulting seconds value fits in the size of an
220 * unsigned int. (It is written this way as a slight optimization;
221 * note that even if both values == INT_MAX, then when added
222 * and getting another 1 added below the result is UINT_MAX.)
224 if ((tv
.tv_sec
> INT_MAX
|| i
->seconds
> INT_MAX
) &&
225 ((long long)tv
.tv_sec
+ i
->seconds
> UINT_MAX
))
226 return (ISC_R_RANGE
);
228 t
->seconds
= tv
.tv_sec
+ i
->seconds
;
229 t
->nanoseconds
= tv
.tv_usec
* NS_PER_US
+ i
->nanoseconds
;
230 if (t
->nanoseconds
>= NS_PER_S
) {
232 t
->nanoseconds
-= NS_PER_S
;
235 return (ISC_R_SUCCESS
);
239 isc_time_compare(const isc_time_t
*t1
, const isc_time_t
*t2
) {
240 REQUIRE(t1
!= NULL
&& t2
!= NULL
);
241 INSIST(t1
->nanoseconds
< NS_PER_S
&& t2
->nanoseconds
< NS_PER_S
);
243 if (t1
->seconds
< t2
->seconds
)
245 if (t1
->seconds
> t2
->seconds
)
247 if (t1
->nanoseconds
< t2
->nanoseconds
)
249 if (t1
->nanoseconds
> t2
->nanoseconds
)
255 isc_time_add(const isc_time_t
*t
, const isc_interval_t
*i
, isc_time_t
*result
)
257 REQUIRE(t
!= NULL
&& i
!= NULL
&& result
!= NULL
);
258 INSIST(t
->nanoseconds
< NS_PER_S
&& i
->nanoseconds
< NS_PER_S
);
261 * Ensure the resulting seconds value fits in the size of an
262 * unsigned int. (It is written this way as a slight optimization;
263 * note that even if both values == INT_MAX, then when added
264 * and getting another 1 added below the result is UINT_MAX.)
266 if ((t
->seconds
> INT_MAX
|| i
->seconds
> INT_MAX
) &&
267 ((long long)t
->seconds
+ i
->seconds
> UINT_MAX
))
268 return (ISC_R_RANGE
);
270 result
->seconds
= t
->seconds
+ i
->seconds
;
271 result
->nanoseconds
= t
->nanoseconds
+ i
->nanoseconds
;
272 if (result
->nanoseconds
>= NS_PER_S
) {
274 result
->nanoseconds
-= NS_PER_S
;
277 return (ISC_R_SUCCESS
);
281 isc_time_subtract(const isc_time_t
*t
, const isc_interval_t
*i
,
284 REQUIRE(t
!= NULL
&& i
!= NULL
&& result
!= NULL
);
285 INSIST(t
->nanoseconds
< NS_PER_S
&& i
->nanoseconds
< NS_PER_S
);
287 if ((unsigned int)t
->seconds
< i
->seconds
||
288 ((unsigned int)t
->seconds
== i
->seconds
&&
289 t
->nanoseconds
< i
->nanoseconds
))
290 return (ISC_R_RANGE
);
292 result
->seconds
= t
->seconds
- i
->seconds
;
293 if (t
->nanoseconds
>= i
->nanoseconds
)
294 result
->nanoseconds
= t
->nanoseconds
- i
->nanoseconds
;
296 result
->nanoseconds
= NS_PER_S
- i
->nanoseconds
+
301 return (ISC_R_SUCCESS
);
305 isc_time_microdiff(const isc_time_t
*t1
, const isc_time_t
*t2
) {
306 isc_uint64_t i1
, i2
, i3
;
308 REQUIRE(t1
!= NULL
&& t2
!= NULL
);
309 INSIST(t1
->nanoseconds
< NS_PER_S
&& t2
->nanoseconds
< NS_PER_S
);
311 i1
= (isc_uint64_t
)t1
->seconds
* NS_PER_S
+ t1
->nanoseconds
;
312 i2
= (isc_uint64_t
)t2
->seconds
* NS_PER_S
+ t2
->nanoseconds
;
320 * Convert to microseconds.
322 i3
= (i1
- i2
) / NS_PER_US
;
328 isc_time_seconds(const isc_time_t
*t
) {
330 INSIST(t
->nanoseconds
< NS_PER_S
);
332 return ((isc_uint32_t
)t
->seconds
);
336 isc_time_secondsastimet(const isc_time_t
*t
, time_t *secondsp
) {
341 INSIST(t
->nanoseconds
< NS_PER_S
);
344 * Ensure that the number of seconds represented by t->seconds
345 * can be represented by a time_t. Since t->seconds is an unsigned
346 * int and since time_t is mostly opaque, this is trickier than
347 * it seems. (This standardized opaqueness of time_t is *very*
348 * frustrating; time_t is not even limited to being an integral
351 * The mission, then, is to avoid generating any kind of warning
352 * about "signed versus unsigned" while trying to determine if the
353 * the unsigned int t->seconds is out range for tv_sec, which is
354 * pretty much only true if time_t is a signed integer of the same
355 * size as the return value of isc_time_seconds.
357 * The use of the 64 bit integer ``i'' takes advantage of C's
358 * conversion rules to either zero fill or sign extend the widened
361 * Solaris 5.6 gives this warning about the left shift:
362 * warning: integer overflow detected: op "<<"
363 * if the U(nsigned) qualifier is not on the 1.
365 seconds
= (time_t)t
->seconds
;
367 INSIST(sizeof(unsigned int) == sizeof(isc_uint32_t
));
368 INSIST(sizeof(time_t) >= sizeof(isc_uint32_t
));
370 if (sizeof(time_t) == sizeof(isc_uint32_t
) && /* Same size. */
371 (time_t)0.5 != 0.5 && /* Not a floating point type. */
372 (i
= (time_t)-1) != 4294967295u && /* Is signed. */
374 (1U << (sizeof(time_t) * CHAR_BIT
- 1))) != 0U) { /* Negative. */
376 * This UNUSED() is here to shut up the IRIX compiler:
377 * variable "i" was set but never used
378 * when the value of i *was* used in the third test.
379 * (Let's hope the compiler got the actual test right.)
382 return (ISC_R_RANGE
);
387 return (ISC_R_SUCCESS
);
391 isc_time_nanoseconds(const isc_time_t
*t
) {
394 ENSURE(t
->nanoseconds
< NS_PER_S
);
396 return ((isc_uint32_t
)t
->nanoseconds
);
400 isc_time_formattimestamp(const isc_time_t
*t
, char *buf
, unsigned int len
) {
406 now
= (time_t) t
->seconds
;
407 flen
= strftime(buf
, len
, "%d-%b-%Y %X", localtime(&now
));
410 snprintf(buf
+ flen
, len
- flen
,
411 ".%03u", t
->nanoseconds
/ 1000000);
413 snprintf(buf
, len
, "99-Bad-9999 99:99:99.999");
417 isc_time_formathttptimestamp(const isc_time_t
*t
, char *buf
, unsigned int len
) {
423 now
= (time_t)t
->seconds
;
424 flen
= strftime(buf
, len
, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now
));
429 isc_time_formatISO8601(const isc_time_t
*t
, char *buf
, unsigned int len
) {
435 now
= (time_t)t
->seconds
;
436 flen
= strftime(buf
, len
, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now
));