]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add ISO time stamps to the microsecond
authorMark Andrews <marka@isc.org>
Tue, 29 Sep 2020 04:58:56 +0000 (14:58 +1000)
committerMark Andrews <marka@isc.org>
Wed, 30 Sep 2020 13:56:18 +0000 (23:56 +1000)
lib/isc/tests/time_test.c
lib/isc/unix/include/isc/time.h
lib/isc/unix/time.c
lib/isc/win32/include/isc/time.h
lib/isc/win32/libisc.def.in
lib/isc/win32/time.c

index 04b732c45a555c60dafa5c13d0207ddef6652deb..1bc039174415c88fecdd7d8eab22435c6587c4cf 100644 (file)
@@ -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),
        };
 
index 06f6253247cb6863ef634d6a9faee674a13e46a1..cb94320109029322a292a9cc58f5186986e8f500 100644 (file)
@@ -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);
 /*%<
index aec430cb6908e320a5d170356123433644df63ff..b7e900aa48b9c4e12277b2b34073d3d474dbd001 100644 (file)
@@ -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) {
index a2db25bd3c2fa355c98312339cbd5fefb693f422..71fda16433a1b3f1ed25db85e5fbd792e0524ab6 100644 (file)
@@ -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);
 /*%<
index 8b87058f7ddb0fb71aca70806a46a888745646a5..8c2ba39c904c6c65bbc4cd6ddac66555d5acb48e 100644 (file)
@@ -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
index 003fa4c037d123fa93d008f99ad1720eea33d2e7..d35cf5e370d68381887ecc5017fa62b39317b658 100644 (file)
@@ -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) {