time.h 9.89 KB
Newer Older
Bob Halley's avatar
Bob Halley committed
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4 5 6
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 8 9
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
Bob Halley's avatar
Bob Halley committed
10
 */
Bob Halley's avatar
add  
Bob Halley committed
11 12 13 14

#ifndef ISC_TIME_H
#define ISC_TIME_H 1

15
#include <errno.h>
16
#include <inttypes.h>
17
#include <stdbool.h>
18
#include <time.h>
19 20 21
#include <windows.h>

#include <isc/lang.h>
22
#include <isc/types.h>
Bob Halley's avatar
add  
Bob Halley committed
23

24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
/***
 *** POSIX Shims
 ***/

inline struct tm *
gmtime_r(const time_t *clock, struct tm *result) {
	errno_t ret = gmtime_s(result, clock);
	if (ret != 0) {
		errno = ret;
		return (NULL);
	}
	return (result);
}

inline struct tm *
localtime_r(const time_t *clock, struct tm *result) {
	errno_t ret = localtime_s(result, clock);
	if (ret != 0) {
		errno = ret;
		return (NULL);
	}
	return (result);
}

Bob Halley's avatar
Bob Halley committed
48 49 50 51 52 53 54 55
/***
 *** Intervals
 ***/

/*
 * The contents of this structure are private, and MUST NOT be accessed
 * directly by callers.
 *
56
 * The contents are exposed only to allow callers to avoid dynamic allocation.
Bob Halley's avatar
Bob Halley committed
57
 */
58
struct isc_interval {
59
	int64_t interval;
60
};
61

62
LIBISC_EXTERNAL_DATA extern const isc_interval_t *const isc_interval_zero;
Bob Halley's avatar
Bob Halley committed
63

Evan Hunt's avatar
Evan Hunt committed
64 65 66 67 68 69 70
/*
 * ISC_FORMATHTTPTIMESTAMP_SIZE needs to be 30 in C locale and potentially
 * more for other locales to handle longer national abbreviations when
 * expanding strftime's %a and %b.
 */
#define ISC_FORMATHTTPTIMESTAMP_SIZE 50

71 72
ISC_LANG_BEGINDECLS

Bob Halley's avatar
Bob Halley committed
73
void
74 75
isc_interval_set(isc_interval_t *i, unsigned int seconds,
		 unsigned int nanoseconds);
Bob Halley's avatar
Bob Halley committed
76 77 78 79 80 81 82
/*
 * Set 'i' to a value representing an interval of 'seconds' seconds and
 * 'nanoseconds' nanoseconds, suitable for use in isc_time_add() and
 * isc_time_subtract().
 *
 * Requires:
 *
83 84
 *	't' is a valid pointer.
 *	nanoseconds < 1000000000.
Bob Halley's avatar
Bob Halley committed
85 86
 */

87
bool
Andreas Gustafsson's avatar
Andreas Gustafsson committed
88
isc_interval_iszero(const isc_interval_t *i);
Bob Halley's avatar
Bob Halley committed
89
/*
90
 * Returns true iff. 'i' is the zero interval.
Bob Halley's avatar
Bob Halley committed
91 92 93
 *
 * Requires:
 *
94
 *	'i' is a valid pointer.
Bob Halley's avatar
Bob Halley committed
95 96 97 98 99 100 101 102 103 104
 */

/***
 *** Absolute Times
 ***/

/*
 * The contents of this structure are private, and MUST NOT be accessed
 * directly by callers.
 *
105
 * The contents are exposed only to allow callers to avoid dynamic allocation.
Bob Halley's avatar
add  
Bob Halley committed
106 107
 */

108
struct isc_time {
Bob Halley's avatar
Bob Halley committed
109
	FILETIME absolute;
110
};
111

112
LIBISC_EXTERNAL_DATA extern const isc_time_t *const isc_time_epoch;
Bob Halley's avatar
add  
Bob Halley committed
113

114 115 116
void
isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds);
/*%<
Automatic Updater's avatar
Automatic Updater committed
117
 * Set 't' to a value which represents the given number of seconds and
118
 * nanoseconds since 00:00:00 January 1, 1970, UTC.
Automatic Updater's avatar
Automatic Updater committed
119
 *
120 121 122 123 124
 * Requires:
 *\li   't' is a valid pointer.
 *\li   nanoseconds < 1000000000.
 */

Bob Halley's avatar
Bob Halley committed
125
void
126
isc_time_settoepoch(isc_time_t *t);
Bob Halley's avatar
Bob Halley committed
127 128 129
/*
 * Set 't' to the time of the epoch.
 *
130 131 132
 * Notes:
 * 	The date of the epoch is platform-dependent.
 *
Bob Halley's avatar
Bob Halley committed
133 134
 * Requires:
 *
135
 *	't' is a valid pointer.
Bob Halley's avatar
Bob Halley committed
136 137
 */

138
bool
Andreas Gustafsson's avatar
Andreas Gustafsson committed
139
isc_time_isepoch(const isc_time_t *t);
Bob Halley's avatar
Bob Halley committed
140
/*
141
 * Returns true iff. 't' is the epoch ("time zero").
Bob Halley's avatar
Bob Halley committed
142 143 144
 *
 * Requires:
 *
145
 *	't' is a valid pointer.
Bob Halley's avatar
Bob Halley committed
146 147
 */

Bob Halley's avatar
add  
Bob Halley committed
148
isc_result_t
149
isc_time_now(isc_time_t *t);
Bob Halley's avatar
add  
Bob Halley committed
150
/*
Bob Halley's avatar
Bob Halley committed
151
 * Set 't' to the current absolute time.
Bob Halley's avatar
add  
Bob Halley committed
152 153 154 155 156 157 158 159 160
 *
 * Requires:
 *
 *	't' is a valid pointer.
 *
 * Returns:
 *
 *	Success
 *	Unexpected error
161 162 163 164
 *		Getting the time from the system failed.
 *	Out of range
 *		The time from the system is too large to be represented
 *		in the current definition of isc_time_t.
Bob Halley's avatar
add  
Bob Halley committed
165 166
 */

167
isc_result_t
Andreas Gustafsson's avatar
Andreas Gustafsson committed
168
isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i);
169 170 171 172 173 174 175 176 177 178 179
/*
 * Set *t to the current absolute time + i.
 *
 * Note:
 *	This call is equivalent to:
 *
 *		isc_time_now(t);
 *		isc_time_add(t, i, t);
 *
 * Requires:
 *
180
 *	't' and 'i' are valid pointers.
181 182 183 184 185
 *
 * Returns:
 *
 *	Success
 *	Unexpected error
186 187 188 189
 *		Getting the time from the system failed.
 *	Out of range
 *		The interval added to the time from the system is too large to
 *		be represented in the current definition of isc_time_t.
190 191
 */

Bob Halley's avatar
add  
Bob Halley committed
192
int
Andreas Gustafsson's avatar
Andreas Gustafsson committed
193
isc_time_compare(const isc_time_t *t1, const isc_time_t *t2);
Bob Halley's avatar
add  
Bob Halley committed
194 195 196 197 198
/*
 * Compare the times referenced by 't1' and 't2'
 *
 * Requires:
 *
199
 *	't1' and 't2' are valid pointers.
Bob Halley's avatar
add  
Bob Halley committed
200 201 202 203 204 205 206 207
 *
 * Returns:
 *
 *	-1		t1 < t2		(comparing times, not pointers)
 *	0		t1 = t2
 *	1		t1 > t2
 */

208
isc_result_t
Andreas Gustafsson's avatar
Andreas Gustafsson committed
209
isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result);
Bob Halley's avatar
add  
Bob Halley committed
210
/*
Bob Halley's avatar
Bob Halley committed
211
 * Add 'i' to 't', storing the result in 'result'.
Bob Halley's avatar
add  
Bob Halley committed
212 213 214
 *
 * Requires:
 *
215
 *	't', 'i', and 'result' are valid pointers.
216 217 218 219 220 221
 *
 * Returns:
 * 	Success
 *	Out of range
 * 		The interval added to the time is too large to
 *		be represented in the current definition of isc_time_t.
Bob Halley's avatar
add  
Bob Halley committed
222 223
 */

224
isc_result_t
Andreas Gustafsson's avatar
Andreas Gustafsson committed
225 226
isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
		  isc_time_t *result);
Bob Halley's avatar
add  
Bob Halley committed
227
/*
Bob Halley's avatar
Bob Halley committed
228
 * Subtract 'i' from 't', storing the result in 'result'.
Bob Halley's avatar
add  
Bob Halley committed
229 230 231
 *
 * Requires:
 *
232
 *	't', 'i', and 'result' are valid pointers.
Bob Halley's avatar
add  
Bob Halley committed
233
 *
234 235 236 237
 * Returns:
 *	Success
 *	Out of range
 *		The interval is larger than the time since the epoch.
Bob Halley's avatar
add  
Bob Halley committed
238 239
 */

240
uint64_t
Andreas Gustafsson's avatar
Andreas Gustafsson committed
241
isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2);
242 243 244 245 246
/*
 * Find the difference in milliseconds between time t1 and time t2.
 * t2 is the subtrahend of t1; ie, difference = t1 - t2.
 *
 * Requires:
247
 *
248
 *	't1' and 't2' are valid pointers.
249 250 251
 *
 * Returns:
 *	The difference of t1 - t2, or 0 if t1 <= t2.
252
 */
Bob Halley's avatar
update  
Bob Halley committed
253

Evan Hunt's avatar
Evan Hunt committed
254 255 256 257 258 259 260 261 262 263
isc_result_t
isc_time_parsehttptimestamp(char *input, isc_time_t *t);
/*%<
 * Parse the time in 'input' into the isc_time_t pointed to by 't',
 * expecting a format like "Mon, 30 Aug 2000 04:06:47 GMT"
 *
 *  Requires:
 *\li      'buf' and 't' are not NULL.
 */

264
uint32_t
Andreas Gustafsson's avatar
Andreas Gustafsson committed
265
isc_time_nanoseconds(const isc_time_t *t);
266 267 268 269
/*
 * Return the number of nanoseconds stored in a time structure.
 *
 * Notes:
270
 *	This is the number of nanoseconds in excess of the number
271 272 273 274
 *	of seconds since the epoch; it will always be less than one
 *	full second.
 *
 * Requires:
275
 *	't' is a valid pointer.
276 277 278 279
 *
 * Ensures:
 *	The returned value is less than 1*10^9.
 */
280

281 282 283 284
void
isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len);
/*
 * Format the time 't' into the buffer 'buf' of length 'len',
285
 * using a format like "30-Aug-2000 04:06:47.997" and the local time zone.
286 287 288 289 290 291 292 293
 * If the text does not fit in the buffer, the result is indeterminate,
 * but is always guaranteed to be null terminated.
 *
 *  Requires:
 *      'len' > 0
 *      'buf' points to an array of at least len chars
 *
 */
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308

void
isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len);
/*
 * Format the time 't' into the buffer 'buf' of length 'len',
 * using a format like "Mon, 30 Aug 2000 04:06:47 GMT"
 * If the text does not fit in the buffer, the result is indeterminate,
 * but is always guaranteed to be null terminated.
 *
 *  Requires:
 *      'len' > 0
 *      'buf' points to an array of at least len chars
 *
 */

Evan Hunt's avatar
Evan Hunt committed
309 310 311 312 313 314 315 316 317 318
isc_result_t
isc_time_parsehttptimestamp(char *input, isc_time_t *t);
/*%<
 * Parse the time in 'input' into the isc_time_t pointed to by 't',
 * expecting a format like "Mon, 30 Aug 2000 04:06:47 GMT"
 *
 *  Requires:
 *\li      'buf' and 't' are not NULL.
 */

319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
void
isc_time_formatISO8601L(const isc_time_t *t, char *buf, unsigned int len);
/*%<
 * Format the time 't' into the buffer 'buf' of length 'len',
 * using the ISO8601 format: "yyyy-mm-ddThh:mm:ss"
 * If the text does not fit in the buffer, the result is indeterminate,
 * but is always guaranteed to be null terminated.
 *
 *  Requires:
 *\li      'len' > 0
 *\li      'buf' points to an array of at least len chars
 *
 */

void
isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len);
/*%<
 * Format the time 't' into the buffer 'buf' of length 'len',
 * using the ISO8601 format: "yyyy-mm-ddThh:mm:ss.sss"
 * If the text does not fit in the buffer, the result is indeterminate,
 * but is always guaranteed to be null terminated.
 *
 *  Requires:
 *\li      'len' > 0
 *\li      'buf' points to an array of at least len chars
 *
 */

347 348 349 350 351 352 353 354 355 356 357
void
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len);
/*%<
 * Format the time 't' into the buffer 'buf' of length 'len',
 * using the ISO8601 format: "yyyy-mm-ddThh:mm:ssZ"
 * If the text does not fit in the buffer, the result is indeterminate,
 * but is always guaranteed to be null terminated.
 *
 *  Requires:
 *\li      'len' > 0
 *\li      'buf' points to an array of at least len chars
358 359 360 361 362 363 364 365 366 367 368 369 370 371
 *
 */

void
isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len);
/*%<
 * Format the time 't' into the buffer 'buf' of length 'len',
 * using the ISO8601 format: "yyyy-mm-ddThh:mm:ss.sssZ"
 * If the text does not fit in the buffer, the result is indeterminate,
 * but is always guaranteed to be null terminated.
 *
 *  Requires:
 *\li      'len' > 0
 *\li      'buf' points to an array of at least len chars
372 373 374 375 376 377 378
 *
 */

void
isc_time_formatshorttimestamp(const isc_time_t *t, char *buf, unsigned int len);
/*%<
 * Format the time 't' into the buffer 'buf' of length 'len',
379
 * using the format "yyyymmddhhmmsssss" useful for file timestamping.
380 381 382 383 384 385
 * If the text does not fit in the buffer, the result is indeterminate,
 * but is always guaranteed to be null terminated.
 *
 *  Requires:
 *\li      'len' > 0
 *\li      'buf' points to an array of at least len chars
386 387 388
 *
 */

389
uint32_t
Mark Andrews's avatar
Mark Andrews committed
390
isc_time_seconds(const isc_time_t *t);
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
/*%<
 * Return the number of seconds since the epoch stored in a time structure.
 *
 * Requires:
 *
 *\li	't' is a valid pointer.
 */

isc_result_t
isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp);
/*%<
 * Ensure the number of seconds in an isc_time_t is representable by a time_t.
 *
 * Notes:
 *\li	The number of seconds stored in an isc_time_t might be larger
 *	than the number of seconds a time_t is able to handle.  Since
 *	time_t is mostly opaque according to the ANSI/ISO standard
 *	(essentially, all you can be sure of is that it is an arithmetic type,
 *	not even necessarily integral), it can be tricky to ensure that
 *	the isc_time_t is in the range a time_t can handle.  Use this
 *	function in place of isc_time_seconds() any time you need to set a
 *	time_t from an isc_time_t.
 *
 * Requires:
 *\li	't' is a valid pointer.
 *
 * Returns:
 *\li	Success
 *\li	Out of range
 */
421

422 423
ISC_LANG_ENDDECLS

Bob Halley's avatar
add  
Bob Halley committed
424
#endif /* ISC_TIME_H */