1 /* 2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 3 * 4 * SPDX-License-Identifier: MPL-2.0 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 9 * 10 * See the COPYRIGHT file distributed with this work for additional 11 * information regarding copyright ownership. 12 */ 13 14 #ifndef ISC_TIME_H 15 #define ISC_TIME_H 1 16 17 #include <errno.h> 18 #include <inttypes.h> 19 #include <stdbool.h> 20 #include <time.h> 21 #include <windows.h> 22 23 #include <isc/lang.h> 24 #include <isc/types.h> 25 26 /*** 27 *** POSIX Shims 28 ***/ 29 30 struct tm * 31 gmtime_r(const time_t *clock, struct tm *result); 32 33 struct tm * 34 localtime_r(const time_t *clock, struct tm *result); 35 36 int 37 nanosleep(const struct timespec *req, struct timespec *rem); 38 39 typedef uint32_t useconds_t; 40 41 int 42 usleep(useconds_t usec); 43 44 /*** 45 *** Intervals 46 ***/ 47 48 /* 49 * The contents of this structure are private, and MUST NOT be accessed 50 * directly by callers. 51 * 52 * The contents are exposed only to allow callers to avoid dynamic allocation. 53 */ 54 struct isc_interval { 55 int64_t interval; 56 }; 57 58 LIBISC_EXTERNAL_DATA extern const isc_interval_t *const isc_interval_zero; 59 60 /* 61 * ISC_FORMATHTTPTIMESTAMP_SIZE needs to be 30 in C locale and potentially 62 * more for other locales to handle longer national abbreviations when 63 * expanding strftime's %a and %b. 64 */ 65 #define ISC_FORMATHTTPTIMESTAMP_SIZE 50 66 67 ISC_LANG_BEGINDECLS 68 69 void 70 isc_interval_set(isc_interval_t *i, unsigned int seconds, 71 unsigned int nanoseconds); 72 /* 73 * Set 'i' to a value representing an interval of 'seconds' seconds and 74 * 'nanoseconds' nanoseconds, suitable for use in isc_time_add() and 75 * isc_time_subtract(). 76 * 77 * Requires: 78 * 79 * 't' is a valid pointer. 80 * nanoseconds < 1000000000. 81 */ 82 83 bool 84 isc_interval_iszero(const isc_interval_t *i); 85 /* 86 * Returns true iff. 'i' is the zero interval. 87 * 88 * Requires: 89 * 90 * 'i' is a valid pointer. 91 */ 92 93 /*** 94 *** Absolute Times 95 ***/ 96 97 /* 98 * The contents of this structure are private, and MUST NOT be accessed 99 * directly by callers. 100 * 101 * The contents are exposed only to allow callers to avoid dynamic allocation. 102 */ 103 104 struct isc_time { 105 FILETIME absolute; 106 }; 107 108 LIBISC_EXTERNAL_DATA extern const isc_time_t *const isc_time_epoch; 109 110 void 111 isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds); 112 /*%< 113 * Set 't' to a value which represents the given number of seconds and 114 * nanoseconds since 00:00:00 January 1, 1970, UTC. 115 * 116 * Requires: 117 *\li 't' is a valid pointer. 118 *\li nanoseconds < 1000000000. 119 */ 120 121 void 122 isc_time_settoepoch(isc_time_t *t); 123 /* 124 * Set 't' to the time of the epoch. 125 * 126 * Notes: 127 * The date of the epoch is platform-dependent. 128 * 129 * Requires: 130 * 131 * 't' is a valid pointer. 132 */ 133 134 bool 135 isc_time_isepoch(const isc_time_t *t); 136 /* 137 * Returns true iff. 't' is the epoch ("time zero"). 138 * 139 * Requires: 140 * 141 * 't' is a valid pointer. 142 */ 143 144 isc_result_t 145 isc_time_now(isc_time_t *t); 146 /* 147 * Set 't' to the current absolute time. 148 * 149 * Requires: 150 * 151 * 't' is a valid pointer. 152 * 153 * Returns: 154 * 155 * Success 156 * Unexpected error 157 * Getting the time from the system failed. 158 * Out of range 159 * The time from the system is too large to be represented 160 * in the current definition of isc_time_t. 161 */ 162 163 isc_result_t 164 isc_time_now_hires(isc_time_t *t); 165 /*%< 166 * Set 't' to the current absolute time. Uses higher resolution clocks 167 * recommended when microsecond accuracy is required. 168 * 169 * Requires: 170 * 171 *\li 't' is a valid pointer. 172 * 173 * Returns: 174 * 175 *\li Success 176 *\li Unexpected error 177 * Getting the time from the system failed. 178 *\li Out of range 179 * The time from the system is too large to be represented 180 * in the current definition of isc_time_t. 181 */ 182 183 isc_result_t 184 isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i); 185 /* 186 * Set *t to the current absolute time + i. 187 * 188 * Note: 189 * This call is equivalent to: 190 * 191 * isc_time_now(t); 192 * isc_time_add(t, i, t); 193 * 194 * Requires: 195 * 196 * 't' and 'i' are valid pointers. 197 * 198 * Returns: 199 * 200 * Success 201 * Unexpected error 202 * Getting the time from the system failed. 203 * Out of range 204 * The interval added to the time from the system is too large to 205 * be represented in the current definition of isc_time_t. 206 */ 207 208 int 209 isc_time_compare(const isc_time_t *t1, const isc_time_t *t2); 210 /* 211 * Compare the times referenced by 't1' and 't2' 212 * 213 * Requires: 214 * 215 * 't1' and 't2' are valid pointers. 216 * 217 * Returns: 218 * 219 * -1 t1 < t2 (comparing times, not pointers) 220 * 0 t1 = t2 221 * 1 t1 > t2 222 */ 223 224 isc_result_t 225 isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result); 226 /* 227 * Add 'i' to 't', storing the result in 'result'. 228 * 229 * Requires: 230 * 231 * 't', 'i', and 'result' are valid pointers. 232 * 233 * Returns: 234 * Success 235 * Out of range 236 * The interval added to the time is too large to 237 * be represented in the current definition of isc_time_t. 238 */ 239 240 isc_result_t 241 isc_time_subtract(const isc_time_t *t, const isc_interval_t *i, 242 isc_time_t *result); 243 /* 244 * Subtract 'i' from 't', storing the result in 'result'. 245 * 246 * Requires: 247 * 248 * 't', 'i', and 'result' are valid pointers. 249 * 250 * Returns: 251 * Success 252 * Out of range 253 * The interval is larger than the time since the epoch. 254 */ 255 256 uint64_t 257 isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2); 258 /* 259 * Find the difference in milliseconds between time t1 and time t2. 260 * t2 is the subtrahend of t1; ie, difference = t1 - t2. 261 * 262 * Requires: 263 * 264 * 't1' and 't2' are valid pointers. 265 * 266 * Returns: 267 * The difference of t1 - t2, or 0 if t1 <= t2. 268 */ 269 270 isc_result_t 271 isc_time_parsehttptimestamp(char *input, isc_time_t *t); 272 /*%< 273 * Parse the time in 'input' into the isc_time_t pointed to by 't', 274 * expecting a format like "Mon, 30 Aug 2000 04:06:47 GMT" 275 * 276 * Requires: 277 *\li 'buf' and 't' are not NULL. 278 */ 279 280 uint32_t 281 isc_time_nanoseconds(const isc_time_t *t); 282 /* 283 * Return the number of nanoseconds stored in a time structure. 284 * 285 * Notes: 286 * This is the number of nanoseconds in excess of the number 287 * of seconds since the epoch; it will always be less than one 288 * full second. 289 * 290 * Requires: 291 * 't' is a valid pointer. 292 * 293 * Ensures: 294 * The returned value is less than 1*10^9. 295 */ 296 297 void 298 isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len); 299 /* 300 * Format the time 't' into the buffer 'buf' of length 'len', 301 * using a format like "30-Aug-2000 04:06:47.997" and the local time zone. 302 * If the text does not fit in the buffer, the result is indeterminate, 303 * but is always guaranteed to be null terminated. 304 * 305 * Requires: 306 * 'len' > 0 307 * 'buf' points to an array of at least len chars 308 * 309 */ 310 311 void 312 isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len); 313 /* 314 * Format the time 't' into the buffer 'buf' of length 'len', 315 * using a format like "Mon, 30 Aug 2000 04:06:47 GMT" 316 * If the text does not fit in the buffer, the result is indeterminate, 317 * but is always guaranteed to be null terminated. 318 * 319 * Requires: 320 * 'len' > 0 321 * 'buf' points to an array of at least len chars 322 * 323 */ 324 325 isc_result_t 326 isc_time_parsehttptimestamp(char *input, isc_time_t *t); 327 /*%< 328 * Parse the time in 'input' into the isc_time_t pointed to by 't', 329 * expecting a format like "Mon, 30 Aug 2000 04:06:47 GMT" 330 * 331 * Requires: 332 *\li 'buf' and 't' are not NULL. 333 */ 334 335 void 336 isc_time_formatISO8601L(const isc_time_t *t, char *buf, unsigned int len); 337 /*%< 338 * Format the time 't' into the buffer 'buf' of length 'len', 339 * using the ISO8601 format: "yyyy-mm-ddThh:mm:ss" 340 * If the text does not fit in the buffer, the result is indeterminate, 341 * but is always guaranteed to be null terminated. 342 * 343 * Requires: 344 *\li 'len' > 0 345 *\li 'buf' points to an array of at least len chars 346 * 347 */ 348 349 void 350 isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len); 351 /*%< 352 * Format the time 't' into the buffer 'buf' of length 'len', 353 * using the ISO8601 format: "yyyy-mm-ddThh:mm:ss.sss" 354 * If the text does not fit in the buffer, the result is indeterminate, 355 * but is always guaranteed to be null terminated. 356 * 357 * Requires: 358 *\li 'len' > 0 359 *\li 'buf' points to an array of at least len chars 360 * 361 */ 362 363 void 364 isc_time_formatISO8601Lus(const isc_time_t *t, char *buf, unsigned int len); 365 /*%< 366 * Format the time 't' into the buffer 'buf' of length 'len', 367 * using the ISO8601 format: "yyyy-mm-ddThh:mm:ss.ssssss" 368 * If the text does not fit in the buffer, the result is indeterminate, 369 * but is always guaranteed to be null terminated. 370 * 371 * Requires: 372 *\li 'len' > 0 373 *\li 'buf' points to an array of at least len chars 374 * 375 */ 376 377 void 378 isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len); 379 /*%< 380 * Format the time 't' into the buffer 'buf' of length 'len', 381 * using the ISO8601 format: "yyyy-mm-ddThh:mm:ssZ" 382 * If the text does not fit in the buffer, the result is indeterminate, 383 * but is always guaranteed to be null terminated. 384 * 385 * Requires: 386 *\li 'len' > 0 387 *\li 'buf' points to an array of at least len chars 388 * 389 */ 390 391 void 392 isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len); 393 /*%< 394 * Format the time 't' into the buffer 'buf' of length 'len', 395 * using the ISO8601 format: "yyyy-mm-ddThh:mm:ss.sssZ" 396 * If the text does not fit in the buffer, the result is indeterminate, 397 * but is always guaranteed to be null terminated. 398 * 399 * Requires: 400 *\li 'len' > 0 401 *\li 'buf' points to an array of at least len chars 402 * 403 */ 404 405 void 406 isc_time_formatISO8601us(const isc_time_t *t, char *buf, unsigned int len); 407 /*%< 408 * Format the time 't' into the buffer 'buf' of length 'len', 409 * using the ISO8601 format: "yyyy-mm-ddThh:mm:ss.ssssssZ" 410 * If the text does not fit in the buffer, the result is indeterminate, 411 * but is always guaranteed to be null terminated. 412 * 413 * Requires: 414 *\li 'len' > 0 415 *\li 'buf' points to an array of at least len chars 416 * 417 */ 418 419 void 420 isc_time_formatshorttimestamp(const isc_time_t *t, char *buf, unsigned int len); 421 /*%< 422 * Format the time 't' into the buffer 'buf' of length 'len', 423 * using the format "yyyymmddhhmmsssss" useful for file timestamping. 424 * If the text does not fit in the buffer, the result is indeterminate, 425 * but is always guaranteed to be null terminated. 426 * 427 * Requires: 428 *\li 'len' > 0 429 *\li 'buf' points to an array of at least len chars 430 * 431 */ 432 433 uint32_t 434 isc_time_seconds(const isc_time_t *t); 435 /*%< 436 * Return the number of seconds since the epoch stored in a time structure. 437 * 438 * Requires: 439 * 440 *\li 't' is a valid pointer. 441 */ 442 443 isc_result_t 444 isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp); 445 /*%< 446 * Ensure the number of seconds in an isc_time_t is representable by a time_t. 447 * 448 * Notes: 449 *\li The number of seconds stored in an isc_time_t might be larger 450 * than the number of seconds a time_t is able to handle. Since 451 * time_t is mostly opaque according to the ANSI/ISO standard 452 * (essentially, all you can be sure of is that it is an arithmetic type, 453 * not even necessarily integral), it can be tricky to ensure that 454 * the isc_time_t is in the range a time_t can handle. Use this 455 * function in place of isc_time_seconds() any time you need to set a 456 * time_t from an isc_time_t. 457 * 458 * Requires: 459 *\li 't' is a valid pointer. 460 * 461 * Returns: 462 *\li Success 463 *\li Out of range 464 */ 465 466 ISC_LANG_ENDDECLS 467 468 #endif /* ISC_TIME_H */ 469