2 * Copyright (C) 2004, 2006-2009 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.52 2009/08/14 07:51:08 marka Exp $ */
31 #include <isc/assertions.h>
36 * struct FILETIME uses "100-nanoseconds intervals".
37 * NS / S = 1000000000 (10^9).
38 * While it is reasonably obvious that this makes the needed
39 * conversion factor 10^7, it is coded this way for additional clarity.
41 #define NS_PER_S 1000000000
42 #define NS_INTERVAL 100
43 #define INTERVALS_PER_S (NS_PER_S / NS_INTERVAL)
44 #define UINT64_MAX _UI64_MAX
50 static isc_time_t epoch = { { 0, 0 } };
51 LIBISC_EXTERNAL_DATA isc_time_t *isc_time_epoch = &epoch;
57 static isc_interval_t zero_interval = { 0 };
58 LIBISC_EXTERNAL_DATA isc_interval_t *isc_interval_zero = &zero_interval;
61 isc_interval_set(isc_interval_t *i, unsigned int seconds,
62 unsigned int nanoseconds)
65 REQUIRE(nanoseconds < NS_PER_S);
68 * This rounds nanoseconds up not down.
70 i->interval = (LONGLONG)seconds * INTERVALS_PER_S
71 + (nanoseconds + NS_INTERVAL - 1) / NS_INTERVAL;
75 isc_interval_iszero(const isc_interval_t *i) {
84 isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) {
85 SYSTEMTIME epoch = { 1970, 1, 4, 1, 0, 0, 0, 0 };
90 REQUIRE(nanoseconds < NS_PER_S);
92 SystemTimeToFileTime(&epoch, &temp);
94 i1.LowPart = t->absolute.dwLowDateTime;
95 i1.HighPart = t->absolute.dwHighDateTime;
97 i1.QuadPart += (unsigned __int64)nanoseconds/100;
98 i1.QuadPart += (unsigned __int64)seconds*10000000;
100 t->absolute.dwLowDateTime = i1.LowPart;
101 t->absolute.dwHighDateTime = i1.HighPart;
105 isc_time_settoepoch(isc_time_t *t) {
108 t->absolute.dwLowDateTime = 0;
109 t->absolute.dwHighDateTime = 0;
113 isc_time_isepoch(const isc_time_t *t) {
116 if (t->absolute.dwLowDateTime == 0 &&
117 t->absolute.dwHighDateTime == 0)
124 isc_time_now(isc_time_t *t) {
127 GetSystemTimeAsFileTime(&t->absolute);
129 return (ISC_R_SUCCESS);
133 isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) {
139 GetSystemTimeAsFileTime(&t->absolute);
141 i1.LowPart = t->absolute.dwLowDateTime;
142 i1.HighPart = t->absolute.dwHighDateTime;
144 if (UINT64_MAX - i1.QuadPart < (unsigned __int64)i->interval)
145 return (ISC_R_RANGE);
147 i1.QuadPart += i->interval;
149 t->absolute.dwLowDateTime = i1.LowPart;
150 t->absolute.dwHighDateTime = i1.HighPart;
152 return (ISC_R_SUCCESS);
156 isc_time_compare(const isc_time_t *t1, const isc_time_t *t2) {
157 REQUIRE(t1 != NULL && t2 != NULL);
159 return ((int)CompareFileTime(&t1->absolute, &t2->absolute));
163 isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result)
167 REQUIRE(t != NULL && i != NULL && result != NULL);
169 i1.LowPart = t->absolute.dwLowDateTime;
170 i1.HighPart = t->absolute.dwHighDateTime;
172 if (UINT64_MAX - i1.QuadPart < (unsigned __int64)i->interval)
173 return (ISC_R_RANGE);
175 i1.QuadPart += i->interval;
177 result->absolute.dwLowDateTime = i1.LowPart;
178 result->absolute.dwHighDateTime = i1.HighPart;
180 return (ISC_R_SUCCESS);
184 isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
185 isc_time_t *result) {
188 REQUIRE(t != NULL && i != NULL && result != NULL);
190 i1.LowPart = t->absolute.dwLowDateTime;
191 i1.HighPart = t->absolute.dwHighDateTime;
193 if (i1.QuadPart < (unsigned __int64) i->interval)
194 return (ISC_R_RANGE);
196 i1.QuadPart -= i->interval;
198 result->absolute.dwLowDateTime = i1.LowPart;
199 result->absolute.dwHighDateTime = i1.HighPart;
201 return (ISC_R_SUCCESS);
205 isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) {
206 ULARGE_INTEGER i1, i2;
209 REQUIRE(t1 != NULL && t2 != NULL);
211 i1.LowPart = t1->absolute.dwLowDateTime;
212 i1.HighPart = t1->absolute.dwHighDateTime;
213 i2.LowPart = t2->absolute.dwLowDateTime;
214 i2.HighPart = t2->absolute.dwHighDateTime;
216 if (i1.QuadPart <= i2.QuadPart)
220 * Convert to microseconds.
222 i3 = (i1.QuadPart - i2.QuadPart) / 10;
228 isc_time_seconds(const isc_time_t *t) {
229 SYSTEMTIME epoch = { 1970, 1, 4, 1, 0, 0, 0, 0 };
231 ULARGE_INTEGER i1, i2;
234 SystemTimeToFileTime(&epoch, &temp);
236 i1.LowPart = t->absolute.dwLowDateTime;
237 i1.HighPart = t->absolute.dwHighDateTime;
238 i2.LowPart = temp.dwLowDateTime;
239 i2.HighPart = temp.dwHighDateTime;
241 i3 = (i1.QuadPart - i2.QuadPart) / 10000000;
243 return ((isc_uint32_t)i3);
247 isc_time_nanoseconds(const isc_time_t *t) {
250 i.LowPart = t->absolute.dwLowDateTime;
251 i.HighPart = t->absolute.dwHighDateTime;
252 return ((isc_uint32_t)(i.QuadPart % 10000000) * 100);
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) {
285 /* strftime() format: "%a, %d %b %Y %H:%M:%S GMT" */
288 if (FileTimeToSystemTime(&t->absolute, &st)) {
289 GetDateFormat(LOCALE_USER_DEFAULT, 0, &st,
290 "ddd',', dd-MMM-yyyy", DateBuf, 50);
291 GetTimeFormat(LOCALE_USER_DEFAULT,
292 TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
293 &st, "hh':'mm':'ss", TimeBuf, 50);
295 snprintf(buf, len, "%s %s GMT", DateBuf, TimeBuf);
302 isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
307 /* strtime() format: "%Y-%m-%dT%H:%M:%SZ" */
310 if (FileTimeToSystemTime(&t->absolute, &st)) {
311 GetDateFormat(LOCALE_NEUTRAL, 0, &st, "yyyy-MM-dd",
313 GetTimeFormat(LOCALE_NEUTRAL,
314 TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
315 &st, "hh':'mm':'ss", TimeBuf, 50);
316 snprintf(buf, len, "%s%sZ", DateBuf, TimeBuf);