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