1*4afad4b7Schristos /* $NetBSD: time.c,v 1.1 2024/02/18 20:57:57 christos Exp $ */
2*4afad4b7Schristos
3*4afad4b7Schristos /*
4*4afad4b7Schristos * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5*4afad4b7Schristos *
6*4afad4b7Schristos * SPDX-License-Identifier: MPL-2.0
7*4afad4b7Schristos *
8*4afad4b7Schristos * This Source Code Form is subject to the terms of the Mozilla Public
9*4afad4b7Schristos * License, v. 2.0. If a copy of the MPL was not distributed with this
10*4afad4b7Schristos * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11*4afad4b7Schristos *
12*4afad4b7Schristos * See the COPYRIGHT file distributed with this work for additional
13*4afad4b7Schristos * information regarding copyright ownership.
14*4afad4b7Schristos */
15*4afad4b7Schristos
16*4afad4b7Schristos /*! \file */
17*4afad4b7Schristos
18*4afad4b7Schristos #include <errno.h>
19*4afad4b7Schristos #include <inttypes.h>
20*4afad4b7Schristos #include <limits.h>
21*4afad4b7Schristos #include <stdbool.h>
22*4afad4b7Schristos #include <stdlib.h>
23*4afad4b7Schristos #include <sys/time.h> /* Required for struct timeval on some platforms. */
24*4afad4b7Schristos #include <syslog.h>
25*4afad4b7Schristos #include <time.h>
26*4afad4b7Schristos
27*4afad4b7Schristos #include <isc/log.h>
28*4afad4b7Schristos #include <isc/platform.h>
29*4afad4b7Schristos #include <isc/print.h>
30*4afad4b7Schristos #include <isc/strerr.h>
31*4afad4b7Schristos #include <isc/string.h>
32*4afad4b7Schristos #include <isc/time.h>
33*4afad4b7Schristos #include <isc/tm.h>
34*4afad4b7Schristos #include <isc/util.h>
35*4afad4b7Schristos
36*4afad4b7Schristos #define NS_PER_S 1000000000 /*%< Nanoseconds per second. */
37*4afad4b7Schristos #define NS_PER_US 1000 /*%< Nanoseconds per microsecond. */
38*4afad4b7Schristos #define NS_PER_MS 1000000 /*%< Nanoseconds per millisecond. */
39*4afad4b7Schristos
40*4afad4b7Schristos #if defined(CLOCK_REALTIME)
41*4afad4b7Schristos #define CLOCKSOURCE_HIRES CLOCK_REALTIME
42*4afad4b7Schristos #endif /* #if defined(CLOCK_REALTIME) */
43*4afad4b7Schristos
44*4afad4b7Schristos #if defined(CLOCK_REALTIME_COARSE)
45*4afad4b7Schristos #define CLOCKSOURCE CLOCK_REALTIME_COARSE
46*4afad4b7Schristos #elif defined(CLOCK_REALTIME_FAST)
47*4afad4b7Schristos #define CLOCKSOURCE CLOCK_REALTIME_FAST
48*4afad4b7Schristos #else /* if defined(CLOCK_REALTIME_COARSE) */
49*4afad4b7Schristos #define CLOCKSOURCE CLOCK_REALTIME
50*4afad4b7Schristos #endif /* if defined(CLOCK_REALTIME_COARSE) */
51*4afad4b7Schristos
52*4afad4b7Schristos #if !defined(CLOCKSOURCE_HIRES)
53*4afad4b7Schristos #define CLOCKSOURCE_HIRES CLOCKSOURCE
54*4afad4b7Schristos #endif /* #ifndef CLOCKSOURCE_HIRES */
55*4afad4b7Schristos
56*4afad4b7Schristos /*%
57*4afad4b7Schristos *** Intervals
58*4afad4b7Schristos ***/
59*4afad4b7Schristos
60*4afad4b7Schristos #if !defined(UNIT_TESTING)
61*4afad4b7Schristos static const isc_interval_t zero_interval = { 0, 0 };
62*4afad4b7Schristos const isc_interval_t *const isc_interval_zero = &zero_interval;
63*4afad4b7Schristos #endif
64*4afad4b7Schristos
65*4afad4b7Schristos void
isc_interval_set(isc_interval_t * i,unsigned int seconds,unsigned int nanoseconds)66*4afad4b7Schristos isc_interval_set(isc_interval_t *i, unsigned int seconds,
67*4afad4b7Schristos unsigned int nanoseconds) {
68*4afad4b7Schristos REQUIRE(i != NULL);
69*4afad4b7Schristos REQUIRE(nanoseconds < NS_PER_S);
70*4afad4b7Schristos
71*4afad4b7Schristos i->seconds = seconds;
72*4afad4b7Schristos i->nanoseconds = nanoseconds;
73*4afad4b7Schristos }
74*4afad4b7Schristos
75*4afad4b7Schristos bool
isc_interval_iszero(const isc_interval_t * i)76*4afad4b7Schristos isc_interval_iszero(const isc_interval_t *i) {
77*4afad4b7Schristos REQUIRE(i != NULL);
78*4afad4b7Schristos INSIST(i->nanoseconds < NS_PER_S);
79*4afad4b7Schristos
80*4afad4b7Schristos if (i->seconds == 0 && i->nanoseconds == 0) {
81*4afad4b7Schristos return (true);
82*4afad4b7Schristos }
83*4afad4b7Schristos
84*4afad4b7Schristos return (false);
85*4afad4b7Schristos }
86*4afad4b7Schristos
87*4afad4b7Schristos /***
88*4afad4b7Schristos *** Absolute Times
89*4afad4b7Schristos ***/
90*4afad4b7Schristos
91*4afad4b7Schristos #if !defined(UNIT_TESTING)
92*4afad4b7Schristos static const isc_time_t epoch = { 0, 0 };
93*4afad4b7Schristos const isc_time_t *const isc_time_epoch = &epoch;
94*4afad4b7Schristos #endif
95*4afad4b7Schristos
96*4afad4b7Schristos void
isc_time_set(isc_time_t * t,unsigned int seconds,unsigned int nanoseconds)97*4afad4b7Schristos isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) {
98*4afad4b7Schristos REQUIRE(t != NULL);
99*4afad4b7Schristos REQUIRE(nanoseconds < NS_PER_S);
100*4afad4b7Schristos
101*4afad4b7Schristos t->seconds = seconds;
102*4afad4b7Schristos t->nanoseconds = nanoseconds;
103*4afad4b7Schristos }
104*4afad4b7Schristos
105*4afad4b7Schristos void
isc_time_settoepoch(isc_time_t * t)106*4afad4b7Schristos isc_time_settoepoch(isc_time_t *t) {
107*4afad4b7Schristos REQUIRE(t != NULL);
108*4afad4b7Schristos
109*4afad4b7Schristos t->seconds = 0;
110*4afad4b7Schristos t->nanoseconds = 0;
111*4afad4b7Schristos }
112*4afad4b7Schristos
113*4afad4b7Schristos bool
isc_time_isepoch(const isc_time_t * t)114*4afad4b7Schristos isc_time_isepoch(const isc_time_t *t) {
115*4afad4b7Schristos REQUIRE(t != NULL);
116*4afad4b7Schristos INSIST(t->nanoseconds < NS_PER_S);
117*4afad4b7Schristos
118*4afad4b7Schristos if (t->seconds == 0 && t->nanoseconds == 0) {
119*4afad4b7Schristos return (true);
120*4afad4b7Schristos }
121*4afad4b7Schristos
122*4afad4b7Schristos return (false);
123*4afad4b7Schristos }
124*4afad4b7Schristos
125*4afad4b7Schristos static isc_result_t
time_now(isc_time_t * t,clockid_t clock)126*4afad4b7Schristos time_now(isc_time_t *t, clockid_t clock) {
127*4afad4b7Schristos struct timespec ts;
128*4afad4b7Schristos char strbuf[ISC_STRERRORSIZE];
129*4afad4b7Schristos
130*4afad4b7Schristos REQUIRE(t != NULL);
131*4afad4b7Schristos
132*4afad4b7Schristos if (clock_gettime(clock, &ts) == -1) {
133*4afad4b7Schristos strerror_r(errno, strbuf, sizeof(strbuf));
134*4afad4b7Schristos UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
135*4afad4b7Schristos return (ISC_R_UNEXPECTED);
136*4afad4b7Schristos }
137*4afad4b7Schristos
138*4afad4b7Schristos if (ts.tv_sec < 0 || ts.tv_nsec < 0 || ts.tv_nsec >= NS_PER_S) {
139*4afad4b7Schristos return (ISC_R_UNEXPECTED);
140*4afad4b7Schristos }
141*4afad4b7Schristos
142*4afad4b7Schristos /*
143*4afad4b7Schristos * Ensure the tv_sec value fits in t->seconds.
144*4afad4b7Schristos */
145*4afad4b7Schristos if (sizeof(ts.tv_sec) > sizeof(t->seconds) &&
146*4afad4b7Schristos ((ts.tv_sec | (unsigned int)-1) ^ (unsigned int)-1) != 0U)
147*4afad4b7Schristos {
148*4afad4b7Schristos return (ISC_R_RANGE);
149*4afad4b7Schristos }
150*4afad4b7Schristos
151*4afad4b7Schristos t->seconds = ts.tv_sec;
152*4afad4b7Schristos t->nanoseconds = ts.tv_nsec;
153*4afad4b7Schristos
154*4afad4b7Schristos return (ISC_R_SUCCESS);
155*4afad4b7Schristos }
156*4afad4b7Schristos
157*4afad4b7Schristos isc_result_t
isc_time_now_hires(isc_time_t * t)158*4afad4b7Schristos isc_time_now_hires(isc_time_t *t) {
159*4afad4b7Schristos return time_now(t, CLOCKSOURCE_HIRES);
160*4afad4b7Schristos }
161*4afad4b7Schristos
162*4afad4b7Schristos isc_result_t
isc_time_now(isc_time_t * t)163*4afad4b7Schristos isc_time_now(isc_time_t *t) {
164*4afad4b7Schristos return time_now(t, CLOCKSOURCE);
165*4afad4b7Schristos }
166*4afad4b7Schristos
167*4afad4b7Schristos isc_result_t
isc_time_nowplusinterval(isc_time_t * t,const isc_interval_t * i)168*4afad4b7Schristos isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) {
169*4afad4b7Schristos struct timespec ts;
170*4afad4b7Schristos char strbuf[ISC_STRERRORSIZE];
171*4afad4b7Schristos
172*4afad4b7Schristos REQUIRE(t != NULL);
173*4afad4b7Schristos REQUIRE(i != NULL);
174*4afad4b7Schristos INSIST(i->nanoseconds < NS_PER_S);
175*4afad4b7Schristos
176*4afad4b7Schristos if (clock_gettime(CLOCKSOURCE, &ts) == -1) {
177*4afad4b7Schristos strerror_r(errno, strbuf, sizeof(strbuf));
178*4afad4b7Schristos UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
179*4afad4b7Schristos return (ISC_R_UNEXPECTED);
180*4afad4b7Schristos }
181*4afad4b7Schristos
182*4afad4b7Schristos if (ts.tv_sec < 0 || ts.tv_nsec < 0 || ts.tv_nsec >= NS_PER_S) {
183*4afad4b7Schristos return (ISC_R_UNEXPECTED);
184*4afad4b7Schristos }
185*4afad4b7Schristos
186*4afad4b7Schristos /*
187*4afad4b7Schristos * Ensure the resulting seconds value fits in the size of an
188*4afad4b7Schristos * unsigned int. (It is written this way as a slight optimization;
189*4afad4b7Schristos * note that even if both values == INT_MAX, then when added
190*4afad4b7Schristos * and getting another 1 added below the result is UINT_MAX.)
191*4afad4b7Schristos */
192*4afad4b7Schristos if ((ts.tv_sec > INT_MAX || i->seconds > INT_MAX) &&
193*4afad4b7Schristos ((long long)ts.tv_sec + i->seconds > UINT_MAX))
194*4afad4b7Schristos {
195*4afad4b7Schristos return (ISC_R_RANGE);
196*4afad4b7Schristos }
197*4afad4b7Schristos
198*4afad4b7Schristos t->seconds = ts.tv_sec + i->seconds;
199*4afad4b7Schristos t->nanoseconds = ts.tv_nsec + i->nanoseconds;
200*4afad4b7Schristos if (t->nanoseconds >= NS_PER_S) {
201*4afad4b7Schristos t->seconds++;
202*4afad4b7Schristos t->nanoseconds -= NS_PER_S;
203*4afad4b7Schristos }
204*4afad4b7Schristos
205*4afad4b7Schristos return (ISC_R_SUCCESS);
206*4afad4b7Schristos }
207*4afad4b7Schristos
208*4afad4b7Schristos int
isc_time_compare(const isc_time_t * t1,const isc_time_t * t2)209*4afad4b7Schristos isc_time_compare(const isc_time_t *t1, const isc_time_t *t2) {
210*4afad4b7Schristos REQUIRE(t1 != NULL && t2 != NULL);
211*4afad4b7Schristos INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
212*4afad4b7Schristos
213*4afad4b7Schristos if (t1->seconds < t2->seconds) {
214*4afad4b7Schristos return (-1);
215*4afad4b7Schristos }
216*4afad4b7Schristos if (t1->seconds > t2->seconds) {
217*4afad4b7Schristos return (1);
218*4afad4b7Schristos }
219*4afad4b7Schristos if (t1->nanoseconds < t2->nanoseconds) {
220*4afad4b7Schristos return (-1);
221*4afad4b7Schristos }
222*4afad4b7Schristos if (t1->nanoseconds > t2->nanoseconds) {
223*4afad4b7Schristos return (1);
224*4afad4b7Schristos }
225*4afad4b7Schristos return (0);
226*4afad4b7Schristos }
227*4afad4b7Schristos
228*4afad4b7Schristos isc_result_t
isc_time_add(const isc_time_t * t,const isc_interval_t * i,isc_time_t * result)229*4afad4b7Schristos isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result) {
230*4afad4b7Schristos REQUIRE(t != NULL && i != NULL && result != NULL);
231*4afad4b7Schristos REQUIRE(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
232*4afad4b7Schristos
233*4afad4b7Schristos /* Seconds */
234*4afad4b7Schristos if (t->seconds > UINT_MAX - i->seconds) {
235*4afad4b7Schristos return (ISC_R_RANGE);
236*4afad4b7Schristos }
237*4afad4b7Schristos result->seconds = t->seconds + i->seconds;
238*4afad4b7Schristos
239*4afad4b7Schristos /* Nanoseconds */
240*4afad4b7Schristos result->nanoseconds = t->nanoseconds + i->nanoseconds;
241*4afad4b7Schristos if (result->nanoseconds >= NS_PER_S) {
242*4afad4b7Schristos if (result->seconds == UINT_MAX) {
243*4afad4b7Schristos return (ISC_R_RANGE);
244*4afad4b7Schristos }
245*4afad4b7Schristos result->nanoseconds -= NS_PER_S;
246*4afad4b7Schristos result->seconds++;
247*4afad4b7Schristos }
248*4afad4b7Schristos
249*4afad4b7Schristos return (ISC_R_SUCCESS);
250*4afad4b7Schristos }
251*4afad4b7Schristos
252*4afad4b7Schristos isc_result_t
isc_time_subtract(const isc_time_t * t,const isc_interval_t * i,isc_time_t * result)253*4afad4b7Schristos isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
254*4afad4b7Schristos isc_time_t *result) {
255*4afad4b7Schristos REQUIRE(t != NULL && i != NULL && result != NULL);
256*4afad4b7Schristos REQUIRE(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
257*4afad4b7Schristos
258*4afad4b7Schristos /* Seconds */
259*4afad4b7Schristos if (t->seconds < i->seconds) {
260*4afad4b7Schristos return (ISC_R_RANGE);
261*4afad4b7Schristos }
262*4afad4b7Schristos result->seconds = t->seconds - i->seconds;
263*4afad4b7Schristos
264*4afad4b7Schristos /* Nanoseconds */
265*4afad4b7Schristos if (t->nanoseconds >= i->nanoseconds) {
266*4afad4b7Schristos result->nanoseconds = t->nanoseconds - i->nanoseconds;
267*4afad4b7Schristos } else {
268*4afad4b7Schristos if (result->seconds == 0) {
269*4afad4b7Schristos return (ISC_R_RANGE);
270*4afad4b7Schristos }
271*4afad4b7Schristos result->seconds--;
272*4afad4b7Schristos result->nanoseconds = NS_PER_S + t->nanoseconds -
273*4afad4b7Schristos i->nanoseconds;
274*4afad4b7Schristos }
275*4afad4b7Schristos
276*4afad4b7Schristos return (ISC_R_SUCCESS);
277*4afad4b7Schristos }
278*4afad4b7Schristos
279*4afad4b7Schristos uint64_t
isc_time_microdiff(const isc_time_t * t1,const isc_time_t * t2)280*4afad4b7Schristos isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) {
281*4afad4b7Schristos uint64_t i1, i2, i3;
282*4afad4b7Schristos
283*4afad4b7Schristos REQUIRE(t1 != NULL && t2 != NULL);
284*4afad4b7Schristos INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
285*4afad4b7Schristos
286*4afad4b7Schristos i1 = (uint64_t)t1->seconds * NS_PER_S + t1->nanoseconds;
287*4afad4b7Schristos i2 = (uint64_t)t2->seconds * NS_PER_S + t2->nanoseconds;
288*4afad4b7Schristos
289*4afad4b7Schristos if (i1 <= i2) {
290*4afad4b7Schristos return (0);
291*4afad4b7Schristos }
292*4afad4b7Schristos
293*4afad4b7Schristos i3 = i1 - i2;
294*4afad4b7Schristos
295*4afad4b7Schristos /*
296*4afad4b7Schristos * Convert to microseconds.
297*4afad4b7Schristos */
298*4afad4b7Schristos i3 /= NS_PER_US;
299*4afad4b7Schristos
300*4afad4b7Schristos return (i3);
301*4afad4b7Schristos }
302*4afad4b7Schristos
303*4afad4b7Schristos uint32_t
isc_time_seconds(const isc_time_t * t)304*4afad4b7Schristos isc_time_seconds(const isc_time_t *t) {
305*4afad4b7Schristos REQUIRE(t != NULL);
306*4afad4b7Schristos INSIST(t->nanoseconds < NS_PER_S);
307*4afad4b7Schristos
308*4afad4b7Schristos return ((uint32_t)t->seconds);
309*4afad4b7Schristos }
310*4afad4b7Schristos
311*4afad4b7Schristos isc_result_t
isc_time_secondsastimet(const isc_time_t * t,time_t * secondsp)312*4afad4b7Schristos isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp) {
313*4afad4b7Schristos time_t seconds;
314*4afad4b7Schristos
315*4afad4b7Schristos REQUIRE(t != NULL);
316*4afad4b7Schristos INSIST(t->nanoseconds < NS_PER_S);
317*4afad4b7Schristos
318*4afad4b7Schristos /*
319*4afad4b7Schristos * Ensure that the number of seconds represented by t->seconds
320*4afad4b7Schristos * can be represented by a time_t. Since t->seconds is an
321*4afad4b7Schristos * unsigned int and since time_t is mostly opaque, this is
322*4afad4b7Schristos * trickier than it seems. (This standardized opaqueness of
323*4afad4b7Schristos * time_t is *very* frustrating; time_t is not even limited to
324*4afad4b7Schristos * being an integral type.)
325*4afad4b7Schristos *
326*4afad4b7Schristos * The mission, then, is to avoid generating any kind of warning
327*4afad4b7Schristos * about "signed versus unsigned" while trying to determine if
328*4afad4b7Schristos * the unsigned int t->seconds is out range for tv_sec,
329*4afad4b7Schristos * which is pretty much only true if time_t is a signed integer
330*4afad4b7Schristos * of the same size as the return value of isc_time_seconds.
331*4afad4b7Schristos *
332*4afad4b7Schristos * If the paradox in the if clause below is true, t->seconds is
333*4afad4b7Schristos * out of range for time_t.
334*4afad4b7Schristos */
335*4afad4b7Schristos seconds = (time_t)t->seconds;
336*4afad4b7Schristos
337*4afad4b7Schristos INSIST(sizeof(unsigned int) == sizeof(uint32_t));
338*4afad4b7Schristos INSIST(sizeof(time_t) >= sizeof(uint32_t));
339*4afad4b7Schristos
340*4afad4b7Schristos if (t->seconds > (~0U >> 1) && seconds <= (time_t)(~0U >> 1)) {
341*4afad4b7Schristos return (ISC_R_RANGE);
342*4afad4b7Schristos }
343*4afad4b7Schristos
344*4afad4b7Schristos *secondsp = seconds;
345*4afad4b7Schristos
346*4afad4b7Schristos return (ISC_R_SUCCESS);
347*4afad4b7Schristos }
348*4afad4b7Schristos
349*4afad4b7Schristos uint32_t
isc_time_nanoseconds(const isc_time_t * t)350*4afad4b7Schristos isc_time_nanoseconds(const isc_time_t *t) {
351*4afad4b7Schristos REQUIRE(t != NULL);
352*4afad4b7Schristos
353*4afad4b7Schristos ENSURE(t->nanoseconds < NS_PER_S);
354*4afad4b7Schristos
355*4afad4b7Schristos return ((uint32_t)t->nanoseconds);
356*4afad4b7Schristos }
357*4afad4b7Schristos
358*4afad4b7Schristos void
isc_time_formattimestamp(const isc_time_t * t,char * buf,unsigned int len)359*4afad4b7Schristos isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
360*4afad4b7Schristos time_t now;
361*4afad4b7Schristos unsigned int flen;
362*4afad4b7Schristos struct tm tm;
363*4afad4b7Schristos
364*4afad4b7Schristos REQUIRE(t != NULL);
365*4afad4b7Schristos INSIST(t->nanoseconds < NS_PER_S);
366*4afad4b7Schristos REQUIRE(buf != NULL);
367*4afad4b7Schristos REQUIRE(len > 0);
368*4afad4b7Schristos
369*4afad4b7Schristos now = (time_t)t->seconds;
370*4afad4b7Schristos flen = strftime(buf, len, "%d-%b-%Y %X", localtime_r(&now, &tm));
371*4afad4b7Schristos INSIST(flen < len);
372*4afad4b7Schristos if (flen != 0) {
373*4afad4b7Schristos snprintf(buf + flen, len - flen, ".%03u",
374*4afad4b7Schristos t->nanoseconds / NS_PER_MS);
375*4afad4b7Schristos } else {
376*4afad4b7Schristos strlcpy(buf, "99-Bad-9999 99:99:99.999", len);
377*4afad4b7Schristos }
378*4afad4b7Schristos }
379*4afad4b7Schristos
380*4afad4b7Schristos void
isc_time_formathttptimestamp(const isc_time_t * t,char * buf,unsigned int len)381*4afad4b7Schristos isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
382*4afad4b7Schristos time_t now;
383*4afad4b7Schristos unsigned int flen;
384*4afad4b7Schristos struct tm tm;
385*4afad4b7Schristos
386*4afad4b7Schristos REQUIRE(t != NULL);
387*4afad4b7Schristos INSIST(t->nanoseconds < NS_PER_S);
388*4afad4b7Schristos REQUIRE(buf != NULL);
389*4afad4b7Schristos REQUIRE(len > 0);
390*4afad4b7Schristos
391*4afad4b7Schristos /*
392*4afad4b7Schristos * 5 spaces, 1 comma, 3 GMT, 2 %d, 4 %Y, 8 %H:%M:%S, 3+ %a, 3+
393*4afad4b7Schristos * %b (29+)
394*4afad4b7Schristos */
395*4afad4b7Schristos now = (time_t)t->seconds;
396*4afad4b7Schristos flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT",
397*4afad4b7Schristos gmtime_r(&now, &tm));
398*4afad4b7Schristos INSIST(flen < len);
399*4afad4b7Schristos }
400*4afad4b7Schristos
401*4afad4b7Schristos isc_result_t
isc_time_parsehttptimestamp(char * buf,isc_time_t * t)402*4afad4b7Schristos isc_time_parsehttptimestamp(char *buf, isc_time_t *t) {
403*4afad4b7Schristos struct tm t_tm;
404*4afad4b7Schristos time_t when;
405*4afad4b7Schristos char *p;
406*4afad4b7Schristos
407*4afad4b7Schristos REQUIRE(buf != NULL);
408*4afad4b7Schristos REQUIRE(t != NULL);
409*4afad4b7Schristos
410*4afad4b7Schristos p = isc_tm_strptime(buf, "%a, %d %b %Y %H:%M:%S", &t_tm);
411*4afad4b7Schristos if (p == NULL) {
412*4afad4b7Schristos return (ISC_R_UNEXPECTED);
413*4afad4b7Schristos }
414*4afad4b7Schristos when = isc_tm_timegm(&t_tm);
415*4afad4b7Schristos if (when == -1) {
416*4afad4b7Schristos return (ISC_R_UNEXPECTED);
417*4afad4b7Schristos }
418*4afad4b7Schristos isc_time_set(t, when, 0);
419*4afad4b7Schristos return (ISC_R_SUCCESS);
420*4afad4b7Schristos }
421*4afad4b7Schristos
422*4afad4b7Schristos void
isc_time_formatISO8601L(const isc_time_t * t,char * buf,unsigned int len)423*4afad4b7Schristos isc_time_formatISO8601L(const isc_time_t *t, char *buf, unsigned int len) {
424*4afad4b7Schristos time_t now;
425*4afad4b7Schristos unsigned int flen;
426*4afad4b7Schristos struct tm tm;
427*4afad4b7Schristos
428*4afad4b7Schristos REQUIRE(t != NULL);
429*4afad4b7Schristos INSIST(t->nanoseconds < NS_PER_S);
430*4afad4b7Schristos REQUIRE(buf != NULL);
431*4afad4b7Schristos REQUIRE(len > 0);
432*4afad4b7Schristos
433*4afad4b7Schristos now = (time_t)t->seconds;
434*4afad4b7Schristos flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%S", localtime_r(&now, &tm));
435*4afad4b7Schristos INSIST(flen < len);
436*4afad4b7Schristos }
437*4afad4b7Schristos
438*4afad4b7Schristos void
isc_time_formatISO8601Lms(const isc_time_t * t,char * buf,unsigned int len)439*4afad4b7Schristos isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len) {
440*4afad4b7Schristos time_t now;
441*4afad4b7Schristos unsigned int flen;
442*4afad4b7Schristos struct tm tm;
443*4afad4b7Schristos
444*4afad4b7Schristos REQUIRE(t != NULL);
445*4afad4b7Schristos INSIST(t->nanoseconds < NS_PER_S);
446*4afad4b7Schristos REQUIRE(buf != NULL);
447*4afad4b7Schristos REQUIRE(len > 0);
448*4afad4b7Schristos
449*4afad4b7Schristos now = (time_t)t->seconds;
450*4afad4b7Schristos flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%S", localtime_r(&now, &tm));
451*4afad4b7Schristos INSIST(flen < len);
452*4afad4b7Schristos if (flen > 0U && len - flen >= 6) {
453*4afad4b7Schristos snprintf(buf + flen, len - flen, ".%03u",
454*4afad4b7Schristos t->nanoseconds / NS_PER_MS);
455*4afad4b7Schristos }
456*4afad4b7Schristos }
457*4afad4b7Schristos
458*4afad4b7Schristos void
isc_time_formatISO8601Lus(const isc_time_t * t,char * buf,unsigned int len)459*4afad4b7Schristos isc_time_formatISO8601Lus(const isc_time_t *t, char *buf, unsigned int len) {
460*4afad4b7Schristos time_t now;
461*4afad4b7Schristos unsigned int flen;
462*4afad4b7Schristos struct tm tm;
463*4afad4b7Schristos
464*4afad4b7Schristos REQUIRE(t != NULL);
465*4afad4b7Schristos INSIST(t->nanoseconds < NS_PER_S);
466*4afad4b7Schristos REQUIRE(buf != NULL);
467*4afad4b7Schristos REQUIRE(len > 0);
468*4afad4b7Schristos
469*4afad4b7Schristos now = (time_t)t->seconds;
470*4afad4b7Schristos flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%S", localtime_r(&now, &tm));
471*4afad4b7Schristos INSIST(flen < len);
472*4afad4b7Schristos if (flen > 0U && len - flen >= 6) {
473*4afad4b7Schristos snprintf(buf + flen, len - flen, ".%06u",
474*4afad4b7Schristos t->nanoseconds / NS_PER_US);
475*4afad4b7Schristos }
476*4afad4b7Schristos }
477*4afad4b7Schristos
478*4afad4b7Schristos void
isc_time_formatISO8601(const isc_time_t * t,char * buf,unsigned int len)479*4afad4b7Schristos isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
480*4afad4b7Schristos time_t now;
481*4afad4b7Schristos unsigned int flen;
482*4afad4b7Schristos struct tm tm;
483*4afad4b7Schristos
484*4afad4b7Schristos REQUIRE(t != NULL);
485*4afad4b7Schristos INSIST(t->nanoseconds < NS_PER_S);
486*4afad4b7Schristos REQUIRE(buf != NULL);
487*4afad4b7Schristos REQUIRE(len > 0);
488*4afad4b7Schristos
489*4afad4b7Schristos now = (time_t)t->seconds;
490*4afad4b7Schristos flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime_r(&now, &tm));
491*4afad4b7Schristos INSIST(flen < len);
492*4afad4b7Schristos }
493*4afad4b7Schristos
494*4afad4b7Schristos void
isc_time_formatISO8601ms(const isc_time_t * t,char * buf,unsigned int len)495*4afad4b7Schristos isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len) {
496*4afad4b7Schristos time_t now;
497*4afad4b7Schristos unsigned int flen;
498*4afad4b7Schristos struct tm tm;
499*4afad4b7Schristos
500*4afad4b7Schristos REQUIRE(t != NULL);
501*4afad4b7Schristos INSIST(t->nanoseconds < NS_PER_S);
502*4afad4b7Schristos REQUIRE(buf != NULL);
503*4afad4b7Schristos REQUIRE(len > 0);
504*4afad4b7Schristos
505*4afad4b7Schristos now = (time_t)t->seconds;
506*4afad4b7Schristos flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime_r(&now, &tm));
507*4afad4b7Schristos INSIST(flen < len);
508*4afad4b7Schristos if (flen > 0U && len - flen >= 5) {
509*4afad4b7Schristos flen -= 1; /* rewind one character (Z) */
510*4afad4b7Schristos snprintf(buf + flen, len - flen, ".%03uZ",
511*4afad4b7Schristos t->nanoseconds / NS_PER_MS);
512*4afad4b7Schristos }
513*4afad4b7Schristos }
514*4afad4b7Schristos
515*4afad4b7Schristos void
isc_time_formatISO8601us(const isc_time_t * t,char * buf,unsigned int len)516*4afad4b7Schristos isc_time_formatISO8601us(const isc_time_t *t, char *buf, unsigned int len) {
517*4afad4b7Schristos time_t now;
518*4afad4b7Schristos unsigned int flen;
519*4afad4b7Schristos struct tm tm;
520*4afad4b7Schristos
521*4afad4b7Schristos REQUIRE(t != NULL);
522*4afad4b7Schristos INSIST(t->nanoseconds < NS_PER_S);
523*4afad4b7Schristos REQUIRE(buf != NULL);
524*4afad4b7Schristos REQUIRE(len > 0);
525*4afad4b7Schristos
526*4afad4b7Schristos now = (time_t)t->seconds;
527*4afad4b7Schristos flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime_r(&now, &tm));
528*4afad4b7Schristos INSIST(flen < len);
529*4afad4b7Schristos if (flen > 0U && len - flen >= 5) {
530*4afad4b7Schristos flen -= 1; /* rewind one character (Z) */
531*4afad4b7Schristos snprintf(buf + flen, len - flen, ".%06uZ",
532*4afad4b7Schristos t->nanoseconds / NS_PER_US);
533*4afad4b7Schristos }
534*4afad4b7Schristos }
535*4afad4b7Schristos
536*4afad4b7Schristos void
isc_time_formatshorttimestamp(const isc_time_t * t,char * buf,unsigned int len)537*4afad4b7Schristos isc_time_formatshorttimestamp(const isc_time_t *t, char *buf,
538*4afad4b7Schristos unsigned int len) {
539*4afad4b7Schristos time_t now;
540*4afad4b7Schristos unsigned int flen;
541*4afad4b7Schristos struct tm tm;
542*4afad4b7Schristos
543*4afad4b7Schristos REQUIRE(t != NULL);
544*4afad4b7Schristos INSIST(t->nanoseconds < NS_PER_S);
545*4afad4b7Schristos REQUIRE(buf != NULL);
546*4afad4b7Schristos REQUIRE(len > 0);
547*4afad4b7Schristos
548*4afad4b7Schristos now = (time_t)t->seconds;
549*4afad4b7Schristos flen = strftime(buf, len, "%Y%m%d%H%M%S", gmtime_r(&now, &tm));
550*4afad4b7Schristos INSIST(flen < len);
551*4afad4b7Schristos if (flen > 0U && len - flen >= 5) {
552*4afad4b7Schristos snprintf(buf + flen, len - flen, "%03u",
553*4afad4b7Schristos t->nanoseconds / NS_PER_MS);
554*4afad4b7Schristos }
555*4afad4b7Schristos }
556