From 64f3419ec1f56a93b6dd48137ca40c945fc06c59 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 20 Jan 2023 13:47:11 +0100 Subject: [PATCH] time-util: add timestamp output style that shows dates only, no times --- src/basic/time-util.c | 22 +++++++++++++++------ src/basic/time-util.h | 1 + src/test/test-time-util.c | 41 ++++++++++++++++++++++++++++----------- 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/src/basic/time-util.c b/src/basic/time-util.c index 791d83a5d8a..b700f364eff 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -326,14 +326,15 @@ char *format_timestamp_style( return snprintf_ok(buf, l, "@" USEC_FMT, t / USEC_PER_SEC); /* round down µs → s */ } - utc = IN_SET(style, TIMESTAMP_UTC, TIMESTAMP_US_UTC); + utc = IN_SET(style, TIMESTAMP_UTC, TIMESTAMP_US_UTC, TIMESTAMP_DATE); us = IN_SET(style, TIMESTAMP_US, TIMESTAMP_US_UTC); - if (l < (size_t) (3 + /* week day */ - 1 + 10 + /* space and date */ - 1 + 8 + /* space and time */ - (us ? 1 + 6 : 0) + /* "." and microsecond part */ - 1 + (utc ? 3 : 1) + /* space and shortest possible zone */ + if (l < (size_t) (3 + /* week day */ + 1 + 10 + /* space and date */ + style == TIMESTAMP_DATE ? 0 : + (1 + 8 + /* space and time */ + (us ? 1 + 6 : 0) + /* "." and microsecond part */ + 1 + (utc ? 3 : 1)) + /* space and shortest possible zone */ 1)) return NULL; /* Not enough space even for the shortest form. */ @@ -344,6 +345,7 @@ char *format_timestamp_style( [TIMESTAMP_US] = "--- XXXX-XX-XX XX:XX:XX.XXXXXX", [TIMESTAMP_UTC] = "--- XXXX-XX-XX XX:XX:XX UTC", [TIMESTAMP_US_UTC] = "--- XXXX-XX-XX XX:XX:XX.XXXXXX UTC", + [TIMESTAMP_DATE] = "--- XXXX-XX-XX", }; assert(l >= strlen(xxx[style]) + 1); @@ -359,6 +361,14 @@ char *format_timestamp_style( assert((size_t) tm.tm_wday < ELEMENTSOF(weekdays)); memcpy(buf, weekdays[tm.tm_wday], 4); + if (style == TIMESTAMP_DATE) { + /* Special format string if only date should be shown. */ + if (strftime(buf + 3, l - 3, " %Y-%m-%d", &tm) <= 0) + return NULL; /* Doesn't fit */ + + return buf; + } + /* Add the main components */ if (strftime(buf + 3, l - 3, " %Y-%m-%d %H:%M:%S", &tm) <= 0) return NULL; /* Doesn't fit */ diff --git a/src/basic/time-util.h b/src/basic/time-util.h index c98f95a5301..c5ae0c98d49 100644 --- a/src/basic/time-util.h +++ b/src/basic/time-util.h @@ -35,6 +35,7 @@ typedef enum TimestampStyle { TIMESTAMP_UTC, TIMESTAMP_US_UTC, TIMESTAMP_UNIX, + TIMESTAMP_DATE, _TIMESTAMP_STYLE_MAX, _TIMESTAMP_STYLE_INVALID = -EINVAL, } TimestampStyle; diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c index 5c415b07b80..33d5b897290 100644 --- a/src/test/test-time-util.c +++ b/src/test/test-time-util.c @@ -365,6 +365,11 @@ TEST(format_timestamp) { assert_se(parse_timestamp(buf, &y) >= 0); assert_se(x == y); + assert_se(format_timestamp_style(buf, sizeof(buf), x, TIMESTAMP_DATE)); + log_debug("%s", buf); + assert_se(parse_timestamp(buf, &y) >= 0); + assert_se(y > usec_sub_unsigned(x, 2 * USEC_PER_DAY) && y < usec_add(x, 2* USEC_PER_DAY)); + assert_se(format_timestamp_relative(buf, sizeof(buf), x)); log_debug("%s", buf); assert_se(parse_timestamp(buf, &y) >= 0); @@ -466,28 +471,42 @@ TEST(format_timestamp_relative) { assert_se(streq(buf, "2 weeks 2 days ago")); } -static void test_format_timestamp_utc_one(usec_t val, const char *result) { +static void test_format_timestamp_one(usec_t val, TimestampStyle style, const char *result) { char buf[FORMAT_TIMESTAMP_MAX]; const char *t; - t = format_timestamp_style(buf, sizeof(buf), val, TIMESTAMP_UTC); + t = format_timestamp_style(buf, sizeof(buf), val, style); assert_se(streq_ptr(t, result)); } -TEST(format_timestamp_utc) { - test_format_timestamp_utc_one(0, NULL); - test_format_timestamp_utc_one(1, "Thu 1970-01-01 00:00:00 UTC"); - test_format_timestamp_utc_one(USEC_PER_SEC, "Thu 1970-01-01 00:00:01 UTC"); +TEST(format_timestamp_range) { + test_format_timestamp_one(0, TIMESTAMP_UTC, NULL); + test_format_timestamp_one(0, TIMESTAMP_DATE, NULL); + test_format_timestamp_one(0, TIMESTAMP_US_UTC, NULL); + + test_format_timestamp_one(1, TIMESTAMP_UTC, "Thu 1970-01-01 00:00:00 UTC"); + test_format_timestamp_one(1, TIMESTAMP_DATE, "Thu 1970-01-01"); + test_format_timestamp_one(1, TIMESTAMP_US_UTC, "Thu 1970-01-01 00:00:00.000001 UTC"); + + test_format_timestamp_one(USEC_PER_SEC, TIMESTAMP_UTC, "Thu 1970-01-01 00:00:01 UTC"); + test_format_timestamp_one(USEC_PER_SEC, TIMESTAMP_DATE, "Thu 1970-01-01"); + test_format_timestamp_one(USEC_PER_SEC, TIMESTAMP_US_UTC, "Thu 1970-01-01 00:00:01.000000 UTC"); #if SIZEOF_TIME_T == 8 - test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Thu 9999-12-30 23:59:59 UTC"); - test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, "--- XXXX-XX-XX XX:XX:XX UTC"); + test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX, TIMESTAMP_UTC, "Thu 9999-12-30 23:59:59 UTC"); + test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX, TIMESTAMP_DATE, "Thu 9999-12-30"); + test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, TIMESTAMP_UTC, "--- XXXX-XX-XX XX:XX:XX UTC"); + test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, TIMESTAMP_US_UTC, "--- XXXX-XX-XX XX:XX:XX.XXXXXX UTC"); + test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, TIMESTAMP_DATE, "--- XXXX-XX-XX"); #elif SIZEOF_TIME_T == 4 - test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Tue 2038-01-19 03:14:07 UTC"); - test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, "--- XXXX-XX-XX XX:XX:XX UTC"); + test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX, TIMESTAMP_UTC, "Tue 2038-01-19 03:14:07 UTC"); + test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX, TIMESTAMP_DATE, "Tue 2038-01-19"); + test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, TIMESTAMP_UTC, "--- XXXX-XX-XX XX:XX:XX UTC"); + test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, TIMESTAMP_US_UTC, "--- XXXX-XX-XX XX:XX:XX.XXXXXX UTC"); + test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, TIMESTAMP_DATE, "--- XXXX-XX-XX"); #endif - test_format_timestamp_utc_one(USEC_INFINITY, NULL); + test_format_timestamp_one(USEC_INFINITY, TIMESTAMP_UTC, NULL); } TEST(deserialize_dual_timestamp) {