mirror of
https://github.com/systemd/systemd
synced 2024-10-15 04:24:19 +00:00
shared/format-table: optionally print timestamps without "left"
This just adds the base functionality and some unit tests. With TABLE_TIMESTAMP_RELATIVE we print "5s ago" and "5s left", with the new TABLE_TIMESTAMP_LEFT, we print "5s ago" but "5s". This is more useful for cases where we generally only want to print timestamps in the future.
This commit is contained in:
parent
81cfea95e5
commit
d5e6f36c7a
|
@ -418,7 +418,7 @@ char *format_timestamp_style(
|
|||
return buf;
|
||||
}
|
||||
|
||||
char *format_timestamp_relative(char *buf, size_t l, usec_t t) {
|
||||
char* format_timestamp_relative_full(char *buf, size_t l, usec_t t, bool implicit_left) {
|
||||
const char *s;
|
||||
usec_t n, d;
|
||||
|
||||
|
@ -428,17 +428,17 @@ char *format_timestamp_relative(char *buf, size_t l, usec_t t) {
|
|||
n = now(CLOCK_REALTIME);
|
||||
if (n > t) {
|
||||
d = n - t;
|
||||
s = "ago";
|
||||
s = " ago";
|
||||
} else {
|
||||
d = t - n;
|
||||
s = "left";
|
||||
s = implicit_left ? "" : " left";
|
||||
}
|
||||
|
||||
if (d >= USEC_PER_YEAR) {
|
||||
usec_t years = d / USEC_PER_YEAR;
|
||||
usec_t months = (d % USEC_PER_YEAR) / USEC_PER_MONTH;
|
||||
|
||||
(void) snprintf(buf, l, USEC_FMT " %s " USEC_FMT " %s %s",
|
||||
(void) snprintf(buf, l, USEC_FMT " %s " USEC_FMT " %s%s",
|
||||
years,
|
||||
years == 1 ? "year" : "years",
|
||||
months,
|
||||
|
@ -448,7 +448,7 @@ char *format_timestamp_relative(char *buf, size_t l, usec_t t) {
|
|||
usec_t months = d / USEC_PER_MONTH;
|
||||
usec_t days = (d % USEC_PER_MONTH) / USEC_PER_DAY;
|
||||
|
||||
(void) snprintf(buf, l, USEC_FMT " %s " USEC_FMT " %s %s",
|
||||
(void) snprintf(buf, l, USEC_FMT " %s " USEC_FMT " %s%s",
|
||||
months,
|
||||
months == 1 ? "month" : "months",
|
||||
days,
|
||||
|
@ -458,39 +458,39 @@ char *format_timestamp_relative(char *buf, size_t l, usec_t t) {
|
|||
usec_t weeks = d / USEC_PER_WEEK;
|
||||
usec_t days = (d % USEC_PER_WEEK) / USEC_PER_DAY;
|
||||
|
||||
(void) snprintf(buf, l, USEC_FMT " %s " USEC_FMT " %s %s",
|
||||
(void) snprintf(buf, l, USEC_FMT " %s " USEC_FMT " %s%s",
|
||||
weeks,
|
||||
weeks == 1 ? "week" : "weeks",
|
||||
days,
|
||||
days == 1 ? "day" : "days",
|
||||
s);
|
||||
} else if (d >= 2*USEC_PER_DAY)
|
||||
(void) snprintf(buf, l, USEC_FMT " days %s", d / USEC_PER_DAY, s);
|
||||
(void) snprintf(buf, l, USEC_FMT " days%s", d / USEC_PER_DAY,s);
|
||||
else if (d >= 25*USEC_PER_HOUR)
|
||||
(void) snprintf(buf, l, "1 day " USEC_FMT "h %s",
|
||||
(void) snprintf(buf, l, "1 day " USEC_FMT "h%s",
|
||||
(d - USEC_PER_DAY) / USEC_PER_HOUR, s);
|
||||
else if (d >= 6*USEC_PER_HOUR)
|
||||
(void) snprintf(buf, l, USEC_FMT "h %s",
|
||||
(void) snprintf(buf, l, USEC_FMT "h%s",
|
||||
d / USEC_PER_HOUR, s);
|
||||
else if (d >= USEC_PER_HOUR)
|
||||
(void) snprintf(buf, l, USEC_FMT "h " USEC_FMT "min %s",
|
||||
(void) snprintf(buf, l, USEC_FMT "h " USEC_FMT "min%s",
|
||||
d / USEC_PER_HOUR,
|
||||
(d % USEC_PER_HOUR) / USEC_PER_MINUTE, s);
|
||||
else if (d >= 5*USEC_PER_MINUTE)
|
||||
(void) snprintf(buf, l, USEC_FMT "min %s",
|
||||
(void) snprintf(buf, l, USEC_FMT "min%s",
|
||||
d / USEC_PER_MINUTE, s);
|
||||
else if (d >= USEC_PER_MINUTE)
|
||||
(void) snprintf(buf, l, USEC_FMT "min " USEC_FMT "s %s",
|
||||
(void) snprintf(buf, l, USEC_FMT "min " USEC_FMT "s%s",
|
||||
d / USEC_PER_MINUTE,
|
||||
(d % USEC_PER_MINUTE) / USEC_PER_SEC, s);
|
||||
else if (d >= USEC_PER_SEC)
|
||||
(void) snprintf(buf, l, USEC_FMT "s %s",
|
||||
(void) snprintf(buf, l, USEC_FMT "s%s",
|
||||
d / USEC_PER_SEC, s);
|
||||
else if (d >= USEC_PER_MSEC)
|
||||
(void) snprintf(buf, l, USEC_FMT "ms %s",
|
||||
(void) snprintf(buf, l, USEC_FMT "ms%s",
|
||||
d / USEC_PER_MSEC, s);
|
||||
else if (d > 0)
|
||||
(void) snprintf(buf, l, USEC_FMT"us %s",
|
||||
(void) snprintf(buf, l, USEC_FMT"us%s",
|
||||
d, s);
|
||||
else
|
||||
(void) snprintf(buf, l, "now");
|
||||
|
@ -499,7 +499,7 @@ char *format_timestamp_relative(char *buf, size_t l, usec_t t) {
|
|||
return buf;
|
||||
}
|
||||
|
||||
char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
|
||||
char* format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
|
||||
static const struct {
|
||||
const char *suffix;
|
||||
usec_t usec;
|
||||
|
|
|
@ -124,9 +124,14 @@ struct timeval* timeval_store(struct timeval *tv, usec_t u);
|
|||
#define TIMEVAL_STORE(u) timeval_store(&(struct timeval) {}, (u))
|
||||
|
||||
char* format_timestamp_style(char *buf, size_t l, usec_t t, TimestampStyle style) _warn_unused_result_;
|
||||
char* format_timestamp_relative(char *buf, size_t l, usec_t t) _warn_unused_result_;
|
||||
char* format_timestamp_relative_full(char *buf, size_t l, usec_t t, bool implicit_left) _warn_unused_result_;
|
||||
char* format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) _warn_unused_result_;
|
||||
|
||||
_warn_unused_result_
|
||||
static inline char* format_timestamp_relative(char *buf, size_t l, usec_t t) {
|
||||
return format_timestamp_relative_full(buf, l, t, false);
|
||||
}
|
||||
|
||||
_warn_unused_result_
|
||||
static inline char* format_timestamp(char *buf, size_t l, usec_t t) {
|
||||
return format_timestamp_style(buf, l, t, TIMESTAMP_PRETTY);
|
||||
|
|
|
@ -297,6 +297,7 @@ static size_t table_data_size(TableDataType type, const void *data) {
|
|||
case TABLE_TIMESTAMP:
|
||||
case TABLE_TIMESTAMP_UTC:
|
||||
case TABLE_TIMESTAMP_RELATIVE:
|
||||
case TABLE_TIMESTAMP_LEFT:
|
||||
case TABLE_TIMESTAMP_DATE:
|
||||
case TABLE_TIMESPAN:
|
||||
case TABLE_TIMESPAN_MSEC:
|
||||
|
@ -896,6 +897,7 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) {
|
|||
case TABLE_TIMESTAMP:
|
||||
case TABLE_TIMESTAMP_UTC:
|
||||
case TABLE_TIMESTAMP_RELATIVE:
|
||||
case TABLE_TIMESTAMP_LEFT:
|
||||
case TABLE_TIMESTAMP_DATE:
|
||||
case TABLE_TIMESPAN:
|
||||
case TABLE_TIMESPAN_MSEC:
|
||||
|
@ -1304,6 +1306,7 @@ static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t
|
|||
case TABLE_TIMESTAMP:
|
||||
case TABLE_TIMESTAMP_UTC:
|
||||
case TABLE_TIMESTAMP_RELATIVE:
|
||||
case TABLE_TIMESTAMP_LEFT:
|
||||
case TABLE_TIMESTAMP_DATE:
|
||||
return CMP(a->timestamp, b->timestamp);
|
||||
|
||||
|
@ -1537,11 +1540,14 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
|
|||
case TABLE_TIMESTAMP:
|
||||
case TABLE_TIMESTAMP_UTC:
|
||||
case TABLE_TIMESTAMP_RELATIVE:
|
||||
case TABLE_TIMESTAMP_LEFT:
|
||||
case TABLE_TIMESTAMP_DATE: {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
char *ret;
|
||||
|
||||
p = new(char, d->type == TABLE_TIMESTAMP_RELATIVE ? FORMAT_TIMESTAMP_RELATIVE_MAX : FORMAT_TIMESTAMP_MAX);
|
||||
p = new(char,
|
||||
IN_SET(d->type, TABLE_TIMESTAMP_RELATIVE, TABLE_TIMESTAMP_LEFT) ?
|
||||
FORMAT_TIMESTAMP_RELATIVE_MAX : FORMAT_TIMESTAMP_MAX);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
|
@ -1552,7 +1558,9 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
|
|||
else if (d->type == TABLE_TIMESTAMP_DATE)
|
||||
ret = format_timestamp_style(p, FORMAT_TIMESTAMP_MAX, d->timestamp, TIMESTAMP_DATE);
|
||||
else
|
||||
ret = format_timestamp_relative(p, FORMAT_TIMESTAMP_RELATIVE_MAX, d->timestamp);
|
||||
ret = format_timestamp_relative_full(
|
||||
p, FORMAT_TIMESTAMP_RELATIVE_MAX, d->timestamp,
|
||||
/* implicit_left= */ d->type == TABLE_TIMESTAMP_LEFT);
|
||||
if (!ret)
|
||||
return "-";
|
||||
|
||||
|
@ -2589,6 +2597,7 @@ static int table_data_to_json(TableData *d, JsonVariant **ret) {
|
|||
case TABLE_TIMESTAMP:
|
||||
case TABLE_TIMESTAMP_UTC:
|
||||
case TABLE_TIMESTAMP_RELATIVE:
|
||||
case TABLE_TIMESTAMP_LEFT:
|
||||
case TABLE_TIMESTAMP_DATE:
|
||||
if (d->timestamp == USEC_INFINITY)
|
||||
return json_variant_new_null(ret);
|
||||
|
|
|
@ -23,6 +23,7 @@ typedef enum TableDataType {
|
|||
TABLE_TIMESTAMP,
|
||||
TABLE_TIMESTAMP_UTC,
|
||||
TABLE_TIMESTAMP_RELATIVE,
|
||||
TABLE_TIMESTAMP_LEFT,
|
||||
TABLE_TIMESTAMP_DATE,
|
||||
TABLE_TIMESPAN,
|
||||
TABLE_TIMESPAN_MSEC,
|
||||
|
|
|
@ -401,6 +401,74 @@ TEST(FORMAT_TIMESTAMP) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(format_timestamp_relative_full) {
|
||||
char buf[CONST_MAX(FORMAT_TIMESTAMP_MAX, FORMAT_TIMESPAN_MAX)];
|
||||
usec_t x;
|
||||
|
||||
/* Years and months */
|
||||
x = now(CLOCK_REALTIME) - (1*USEC_PER_YEAR + 1*USEC_PER_MONTH);
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, true));
|
||||
log_debug("%s", buf);
|
||||
assert_se(streq(buf, "1 year 1 month ago"));
|
||||
|
||||
x = now(CLOCK_REALTIME) - (1*USEC_PER_YEAR + 2*USEC_PER_MONTH);
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, true));
|
||||
log_debug("%s", buf);
|
||||
assert_se(streq(buf, "1 year 2 months ago"));
|
||||
|
||||
x = now(CLOCK_REALTIME) - (2*USEC_PER_YEAR + 1*USEC_PER_MONTH);
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, true));
|
||||
log_debug("%s", buf);
|
||||
assert_se(streq(buf, "2 years 1 month ago"));
|
||||
|
||||
x = now(CLOCK_REALTIME) - (2*USEC_PER_YEAR + 2*USEC_PER_MONTH);
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, true));
|
||||
log_debug("%s", buf);
|
||||
assert_se(streq(buf, "2 years 2 months ago"));
|
||||
|
||||
/* Months and days */
|
||||
x = now(CLOCK_REALTIME) - (1*USEC_PER_MONTH + 1*USEC_PER_DAY);
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, true));
|
||||
log_debug("%s", buf);
|
||||
assert_se(streq(buf, "1 month 1 day ago"));
|
||||
|
||||
x = now(CLOCK_REALTIME) - (1*USEC_PER_MONTH + 2*USEC_PER_DAY);
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, true));
|
||||
log_debug("%s", buf);
|
||||
assert_se(streq(buf, "1 month 2 days ago"));
|
||||
|
||||
x = now(CLOCK_REALTIME) - (2*USEC_PER_MONTH + 1*USEC_PER_DAY);
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, true));
|
||||
log_debug("%s", buf);
|
||||
assert_se(streq(buf, "2 months 1 day ago"));
|
||||
|
||||
x = now(CLOCK_REALTIME) - (2*USEC_PER_MONTH + 2*USEC_PER_DAY);
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, true));
|
||||
log_debug("%s", buf);
|
||||
assert_se(streq(buf, "2 months 2 days ago"));
|
||||
|
||||
/* Weeks and days */
|
||||
x = now(CLOCK_REALTIME) - (1*USEC_PER_WEEK + 1*USEC_PER_DAY);
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, true));
|
||||
log_debug("%s", buf);
|
||||
assert_se(streq(buf, "1 week 1 day ago"));
|
||||
|
||||
x = now(CLOCK_REALTIME) - (1*USEC_PER_WEEK + 2*USEC_PER_DAY);
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, true));
|
||||
log_debug("%s", buf);
|
||||
assert_se(streq(buf, "1 week 2 days ago"));
|
||||
|
||||
x = now(CLOCK_REALTIME) - (2*USEC_PER_WEEK + 1*USEC_PER_DAY);
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, true));
|
||||
log_debug("%s", buf);
|
||||
assert_se(streq(buf, "2 weeks 1 day ago"));
|
||||
|
||||
x = now(CLOCK_REALTIME) - (2*USEC_PER_WEEK + 2*USEC_PER_DAY);
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, true));
|
||||
log_debug("%s", buf);
|
||||
assert_se(streq(buf, "2 weeks 2 days ago"));
|
||||
}
|
||||
|
||||
TEST(format_timestamp_relative) {
|
||||
char buf[CONST_MAX(FORMAT_TIMESTAMP_MAX, FORMAT_TIMESPAN_MAX)];
|
||||
usec_t x;
|
||||
|
|
Loading…
Reference in a new issue