From: Mark Andrews Date: Tue, 29 Sep 2020 04:58:56 +0000 (+1000) Subject: Add ISO time stamps to the microsecond X-Git-Tag: v9.17.6~24^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=519b070618050ca221779bc61cad4695e2d985e1;p=thirdparty%2Fbind9.git Add ISO time stamps to the microsecond --- diff --git a/lib/isc/tests/time_test.c b/lib/isc/tests/time_test.c index 04b732c45a5..1bc03917441 100644 --- a/lib/isc/tests/time_test.c +++ b/lib/isc/tests/time_test.c @@ -118,6 +118,43 @@ isc_time_formatISO8601ms_test(void **state) { assert_string_equal(buf, "2015-12-13T09:46:40.123Z"); } +/* print UTC in ISO8601 with microseconds */ +static void +isc_time_formatISO8601us_test(void **state) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyy-mm-ddThh:mm:ss.ssssssZ */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatISO8601us(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 27); + assert_int_equal(buf[4], '-'); + assert_int_equal(buf[7], '-'); + assert_int_equal(buf[10], 'T'); + assert_int_equal(buf[13], ':'); + assert_int_equal(buf[16], ':'); + assert_int_equal(buf[19], '.'); + assert_int_equal(buf[26], 'Z'); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatISO8601us(&t, buf, sizeof(buf)); + assert_string_equal(buf, "1970-01-01T00:00:00.000000Z"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123456000); + isc_time_formatISO8601us(&t, buf, sizeof(buf)); + assert_string_equal(buf, "2015-12-13T09:46:40.123456Z"); +} + /* print local time in ISO8601 */ static void isc_time_formatISO8601L_test(void **state) { @@ -189,6 +226,42 @@ isc_time_formatISO8601Lms_test(void **state) { assert_string_equal(buf, "2015-12-13T01:46:40.123"); } +/* print local time in ISO8601 with microseconds */ +static void +isc_time_formatISO8601Lus_test(void **state) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyy-mm-ddThh:mm:ss.ssssss */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatISO8601Lus(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 26); + assert_int_equal(buf[4], '-'); + assert_int_equal(buf[7], '-'); + assert_int_equal(buf[10], 'T'); + assert_int_equal(buf[13], ':'); + assert_int_equal(buf[16], ':'); + assert_int_equal(buf[19], '.'); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatISO8601Lus(&t, buf, sizeof(buf)); + assert_string_equal(buf, "1969-12-31T16:00:00.000000"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123456000); + isc_time_formatISO8601Lus(&t, buf, sizeof(buf)); + assert_string_equal(buf, "2015-12-13T01:46:40.123456"); +} + /* print UTC time as yyyymmddhhmmsssss */ static void isc_time_formatshorttimestamp_test(void **state) { @@ -225,8 +298,10 @@ main(void) { cmocka_unit_test(isc_time_parsehttptimestamp_test), cmocka_unit_test(isc_time_formatISO8601_test), cmocka_unit_test(isc_time_formatISO8601ms_test), + cmocka_unit_test(isc_time_formatISO8601us_test), cmocka_unit_test(isc_time_formatISO8601L_test), cmocka_unit_test(isc_time_formatISO8601Lms_test), + cmocka_unit_test(isc_time_formatISO8601Lus_test), cmocka_unit_test(isc_time_formatshorttimestamp_test), }; diff --git a/lib/isc/unix/include/isc/time.h b/lib/isc/unix/include/isc/time.h index 06f6253247c..cb943201090 100644 --- a/lib/isc/unix/include/isc/time.h +++ b/lib/isc/unix/include/isc/time.h @@ -355,6 +355,20 @@ isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len); * */ +void +isc_time_formatISO8601Lus(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.ssssss" + * 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_formatISO8601(const isc_time_t *t, char *buf, unsigned int len); /*%< @@ -383,6 +397,20 @@ isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len); * */ +void +isc_time_formatISO8601us(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.ssssssZ" + * 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_formatshorttimestamp(const isc_time_t *t, char *buf, unsigned int len); /*%< diff --git a/lib/isc/unix/time.c b/lib/isc/unix/time.c index aec430cb690..b7e900aa48b 100644 --- a/lib/isc/unix/time.c +++ b/lib/isc/unix/time.c @@ -429,6 +429,26 @@ isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len) { } } +void +isc_time_formatISO8601Lus(const isc_time_t *t, char *buf, unsigned int len) { + time_t now; + unsigned int flen; + struct tm tm; + + REQUIRE(t != NULL); + INSIST(t->nanoseconds < NS_PER_S); + REQUIRE(buf != NULL); + REQUIRE(len > 0); + + now = (time_t)t->seconds; + flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%S", localtime_r(&now, &tm)); + INSIST(flen < len); + if (flen > 0U && len - flen >= 6) { + snprintf(buf + flen, len - flen, ".%06u", + t->nanoseconds / NS_PER_US); + } +} + void isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) { time_t now; @@ -466,6 +486,27 @@ isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len) { } } +void +isc_time_formatISO8601us(const isc_time_t *t, char *buf, unsigned int len) { + time_t now; + unsigned int flen; + struct tm tm; + + REQUIRE(t != NULL); + INSIST(t->nanoseconds < NS_PER_S); + REQUIRE(buf != NULL); + REQUIRE(len > 0); + + now = (time_t)t->seconds; + flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime_r(&now, &tm)); + INSIST(flen < len); + if (flen > 0U && len - flen >= 5) { + flen -= 1; /* rewind one character (Z) */ + snprintf(buf + flen, len - flen, ".%06uZ", + t->nanoseconds / NS_PER_US); + } +} + void isc_time_formatshorttimestamp(const isc_time_t *t, char *buf, unsigned int len) { diff --git a/lib/isc/win32/include/isc/time.h b/lib/isc/win32/include/isc/time.h index a2db25bd3c2..71fda16433a 100644 --- a/lib/isc/win32/include/isc/time.h +++ b/lib/isc/win32/include/isc/time.h @@ -344,6 +344,20 @@ isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len); * */ +void +isc_time_formatISO8601Lus(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.ssssss" + * 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_formatISO8601(const isc_time_t *t, char *buf, unsigned int len); /*%< @@ -372,6 +386,20 @@ isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len); * */ +void +isc_time_formatISO8601us(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.ssssssZ" + * 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_formatshorttimestamp(const isc_time_t *t, char *buf, unsigned int len); /*%< diff --git a/lib/isc/win32/libisc.def.in b/lib/isc/win32/libisc.def.in index 8b87058f7dd..8c2ba39c904 100644 --- a/lib/isc/win32/libisc.def.in +++ b/lib/isc/win32/libisc.def.in @@ -667,7 +667,11 @@ isc_thread_setname isc_time_add isc_time_compare isc_time_formatISO8601 +isc_time_formatISO8601L +isc_time_formatISO8601Lms +isc_time_formatISO8601Lus isc_time_formatISO8601ms +isc_time_formatISO8601us isc_time_formathttptimestamp isc_time_formatshorttimestamp isc_time_formattimestamp diff --git a/lib/isc/win32/time.c b/lib/isc/win32/time.c index 003fa4c037d..d35cf5e370d 100644 --- a/lib/isc/win32/time.c +++ b/lib/isc/win32/time.c @@ -403,6 +403,35 @@ isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len) { } } +void +isc_time_formatISO8601Lus(const isc_time_t *t, char *buf, unsigned int len) { + SYSTEMTIME st; + char DateBuf[50]; + char TimeBuf[50]; + + /* strtime() format: "%Y-%m-%dT%H:%M:%S.SSSSSS" */ + + REQUIRE(t != NULL); + REQUIRE(buf != NULL); + REQUIRE(len > 0); + + if (FileTimeToSystemTime(&t->absolute, &st)) { + ULARGE_INTEGER i; + + GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, "yyyy-MM-dd", + DateBuf, 50); + GetTimeFormat(LOCALE_USER_DEFAULT, + TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &st, + "hh':'mm':'ss", TimeBuf, 50); + i.LowPart = t->absolute.dwLowDateTime; + i.HighPart = t->absolute.dwHighDateTime; + snprintf(buf, len, "%sT%s.%06u", DateBuf, TimeBuf, + (uint32_t)(i.QuadPart % 10000000) / 10); + } else { + buf[0] = 0; + } +} + void isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) { SYSTEMTIME st; @@ -452,6 +481,35 @@ isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len) { } } +void +isc_time_formatISO8601us(const isc_time_t *t, char *buf, unsigned int len) { + SYSTEMTIME st; + char DateBuf[50]; + char TimeBuf[50]; + + /* strtime() format: "%Y-%m-%dT%H:%M:%S.SSSSSSZ" */ + + REQUIRE(t != NULL); + REQUIRE(buf != NULL); + REQUIRE(len > 0); + + if (FileTimeToSystemTime(&t->absolute, &st)) { + ULARGE_INTEGER i; + + GetDateFormat(LOCALE_NEUTRAL, 0, &st, "yyyy-MM-dd", DateBuf, + 50); + GetTimeFormat(LOCALE_NEUTRAL, + TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &st, + "hh':'mm':'ss", TimeBuf, 50); + i.LowPart = t->absolute.dwLowDateTime; + i.HighPart = t->absolute.dwHighDateTime; + snprintf(buf, len, "%sT%s.%06uZ", DateBuf, TimeBuf, + (uint32_t)(i.QuadPart % 10000000) / 10); + } else { + buf[0] = 0; + } +} + void isc_time_formatshorttimestamp(const isc_time_t *t, char *buf, unsigned int len) {