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