mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 18:23:32 +08:00
Merge pull request #27786 from YHNdnzj/format-timestamp-monotonic
time-util,format-table: add relative_monotonic variant for timestamp
This commit is contained in:
commit
d4fd160f69
@ -422,7 +422,7 @@ char *format_timestamp_style(
|
||||
return buf;
|
||||
}
|
||||
|
||||
char* format_timestamp_relative_full(char *buf, size_t l, usec_t t, bool implicit_left) {
|
||||
char* format_timestamp_relative_full(char *buf, size_t l, usec_t t, clockid_t clock, bool implicit_left) {
|
||||
const char *s;
|
||||
usec_t n, d;
|
||||
|
||||
@ -431,7 +431,7 @@ char* format_timestamp_relative_full(char *buf, size_t l, usec_t t, bool implici
|
||||
if (!timestamp_is_set(t))
|
||||
return NULL;
|
||||
|
||||
n = now(CLOCK_REALTIME);
|
||||
n = now(clock);
|
||||
if (n > t) {
|
||||
d = n - t;
|
||||
s = " ago";
|
||||
|
@ -123,12 +123,16 @@ 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_full(char *buf, size_t l, usec_t t, bool implicit_left) _warn_unused_result_;
|
||||
char* format_timestamp_relative_full(char *buf, size_t l, usec_t t, clockid_t clock, 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);
|
||||
static inline char* format_timestamp_relative(char *buf, size_t l, usec_t t) {
|
||||
return format_timestamp_relative_full(buf, l, t, CLOCK_REALTIME, /* implicit_left = */ false);
|
||||
}
|
||||
_warn_unused_result_
|
||||
static inline char* format_timestamp_relative_monotonic(char *buf, size_t l, usec_t t) {
|
||||
return format_timestamp_relative_full(buf, l, t, CLOCK_MONOTONIC, /* implicit_left = */ false);
|
||||
}
|
||||
|
||||
_warn_unused_result_
|
||||
@ -142,6 +146,8 @@ static inline char* format_timestamp(char *buf, size_t l, usec_t t) {
|
||||
#define FORMAT_TIMESTAMP(t) format_timestamp((char[FORMAT_TIMESTAMP_MAX]){}, FORMAT_TIMESTAMP_MAX, t)
|
||||
#define FORMAT_TIMESTAMP_RELATIVE(t) \
|
||||
format_timestamp_relative((char[FORMAT_TIMESTAMP_RELATIVE_MAX]){}, FORMAT_TIMESTAMP_RELATIVE_MAX, t)
|
||||
#define FORMAT_TIMESTAMP_RELATIVE_MONOTONIC(t) \
|
||||
format_timestamp_relative_monotonic((char[FORMAT_TIMESTAMP_RELATIVE_MAX]){}, FORMAT_TIMESTAMP_RELATIVE_MAX, t)
|
||||
#define FORMAT_TIMESPAN(t, accuracy) format_timespan((char[FORMAT_TIMESPAN_MAX]){}, FORMAT_TIMESPAN_MAX, t, accuracy)
|
||||
#define FORMAT_TIMESTAMP_STYLE(t, style) \
|
||||
format_timestamp_style((char[FORMAT_TIMESTAMP_MAX]){}, FORMAT_TIMESTAMP_MAX, t, style)
|
||||
|
@ -74,7 +74,7 @@ typedef struct SessionStatusInfo {
|
||||
const char *scope;
|
||||
const char *desktop;
|
||||
bool idle_hint;
|
||||
usec_t idle_hint_timestamp;
|
||||
dual_timestamp idle_hint_timestamp;
|
||||
} SessionStatusInfo;
|
||||
|
||||
typedef struct UserStatusInfo {
|
||||
@ -173,10 +173,10 @@ static int show_table(Table *table, const char *word) {
|
||||
static int list_sessions(int argc, char *argv[], void *userdata) {
|
||||
|
||||
static const struct bus_properties_map map[] = {
|
||||
{ "IdleHint", "b", NULL, offsetof(SessionStatusInfo, idle_hint) },
|
||||
{ "IdleSinceHint", "t", NULL, offsetof(SessionStatusInfo, idle_hint_timestamp) },
|
||||
{ "State", "s", NULL, offsetof(SessionStatusInfo, state) },
|
||||
{ "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
|
||||
{ "IdleHint", "b", NULL, offsetof(SessionStatusInfo, idle_hint) },
|
||||
{ "IdleSinceHintMonotonic", "t", NULL, offsetof(SessionStatusInfo, idle_hint_timestamp.monotonic) },
|
||||
{ "State", "s", NULL, offsetof(SessionStatusInfo, state) },
|
||||
{ "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
|
||||
{},
|
||||
};
|
||||
|
||||
@ -240,7 +240,7 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
|
||||
return table_log_add_error(r);
|
||||
|
||||
if (i.idle_hint)
|
||||
r = table_add_cell(table, NULL, TABLE_TIMESTAMP_RELATIVE, &i.idle_hint_timestamp);
|
||||
r = table_add_cell(table, NULL, TABLE_TIMESTAMP_RELATIVE_MONOTONIC, &i.idle_hint_timestamp.monotonic);
|
||||
else
|
||||
r = table_add_cell(table, NULL, TABLE_EMPTY, NULL);
|
||||
if (r < 0)
|
||||
@ -470,27 +470,28 @@ static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_messag
|
||||
static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
|
||||
|
||||
static const struct bus_properties_map map[] = {
|
||||
{ "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
|
||||
{ "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
|
||||
{ "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
|
||||
{ "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
|
||||
{ "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
|
||||
{ "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
|
||||
{ "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
|
||||
{ "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
|
||||
{ "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
|
||||
{ "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
|
||||
{ "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
|
||||
{ "State", "s", NULL, offsetof(SessionStatusInfo, state) },
|
||||
{ "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
|
||||
{ "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
|
||||
{ "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
|
||||
{ "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) },
|
||||
{ "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) },
|
||||
{ "IdleHint", "b", NULL, offsetof(SessionStatusInfo, idle_hint) },
|
||||
{ "IdleSinceHint", "t", NULL, offsetof(SessionStatusInfo, idle_hint_timestamp) },
|
||||
{ "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
|
||||
{ "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
|
||||
{ "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
|
||||
{ "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
|
||||
{ "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
|
||||
{ "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
|
||||
{ "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
|
||||
{ "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
|
||||
{ "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
|
||||
{ "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
|
||||
{ "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
|
||||
{ "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
|
||||
{ "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
|
||||
{ "State", "s", NULL, offsetof(SessionStatusInfo, state) },
|
||||
{ "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
|
||||
{ "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
|
||||
{ "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
|
||||
{ "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) },
|
||||
{ "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) },
|
||||
{ "IdleHint", "b", NULL, offsetof(SessionStatusInfo, idle_hint) },
|
||||
{ "IdleSinceHint", "t", NULL, offsetof(SessionStatusInfo, idle_hint_timestamp.realtime) },
|
||||
{ "IdleSinceHintMonotonic", "t", NULL, offsetof(SessionStatusInfo, idle_hint_timestamp.monotonic) },
|
||||
{ "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
|
||||
{ "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
|
||||
{}
|
||||
};
|
||||
|
||||
@ -515,10 +516,10 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
|
||||
else
|
||||
printf(UID_FMT "\n", i.uid);
|
||||
|
||||
if (timestamp_is_set(i.timestamp.realtime))
|
||||
if (dual_timestamp_is_set(&i.timestamp))
|
||||
printf("\t Since: %s; %s\n",
|
||||
FORMAT_TIMESTAMP(i.timestamp.realtime),
|
||||
FORMAT_TIMESTAMP_RELATIVE(i.timestamp.realtime));
|
||||
FORMAT_TIMESTAMP_RELATIVE_MONOTONIC(i.timestamp.monotonic));
|
||||
|
||||
if (i.leader > 0) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
@ -581,11 +582,11 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
|
||||
if (i.state)
|
||||
printf("\t State: %s\n", i.state);
|
||||
|
||||
if (i.idle_hint && timestamp_is_set(i.idle_hint_timestamp))
|
||||
if (i.idle_hint && dual_timestamp_is_set(&i.idle_hint_timestamp))
|
||||
printf("\t Idle: %s since %s (%s)\n",
|
||||
yes_no(i.idle_hint),
|
||||
FORMAT_TIMESTAMP(i.idle_hint_timestamp),
|
||||
FORMAT_TIMESTAMP_RELATIVE(i.idle_hint_timestamp));
|
||||
FORMAT_TIMESTAMP(i.idle_hint_timestamp.realtime),
|
||||
FORMAT_TIMESTAMP_RELATIVE_MONOTONIC(i.idle_hint_timestamp.monotonic));
|
||||
else
|
||||
printf("\t Idle: %s\n", yes_no(i.idle_hint));
|
||||
|
||||
@ -646,10 +647,10 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
|
||||
else
|
||||
printf("%"PRIu32"\n", i.uid);
|
||||
|
||||
if (timestamp_is_set(i.timestamp.realtime))
|
||||
if (dual_timestamp_is_set(&i.timestamp))
|
||||
printf("\t Since: %s; %s\n",
|
||||
FORMAT_TIMESTAMP(i.timestamp.realtime),
|
||||
FORMAT_TIMESTAMP_RELATIVE(i.timestamp.realtime));
|
||||
FORMAT_TIMESTAMP_RELATIVE_MONOTONIC(i.timestamp.monotonic));
|
||||
|
||||
if (!isempty(i.state))
|
||||
printf("\t State: %s\n", i.state);
|
||||
@ -692,9 +693,9 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
|
||||
static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) {
|
||||
|
||||
static const struct bus_properties_map map[] = {
|
||||
{ "Id", "s", NULL, offsetof(SeatStatusInfo, id) },
|
||||
{ "Id", "s", NULL, offsetof(SeatStatusInfo, id) },
|
||||
{ "ActiveSession", "(so)", prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) },
|
||||
{ "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) },
|
||||
{ "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -300,6 +300,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_RELATIVE_MONOTONIC:
|
||||
case TABLE_TIMESTAMP_LEFT:
|
||||
case TABLE_TIMESTAMP_DATE:
|
||||
case TABLE_TIMESPAN:
|
||||
@ -905,6 +906,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_RELATIVE_MONOTONIC:
|
||||
case TABLE_TIMESTAMP_LEFT:
|
||||
case TABLE_TIMESTAMP_DATE:
|
||||
case TABLE_TIMESPAN:
|
||||
@ -1322,6 +1324,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_RELATIVE_MONOTONIC:
|
||||
case TABLE_TIMESTAMP_LEFT:
|
||||
case TABLE_TIMESTAMP_DATE:
|
||||
return CMP(a->timestamp, b->timestamp);
|
||||
@ -1564,13 +1567,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_RELATIVE_MONOTONIC:
|
||||
case TABLE_TIMESTAMP_LEFT:
|
||||
case TABLE_TIMESTAMP_DATE: {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
char *ret;
|
||||
|
||||
p = new(char,
|
||||
IN_SET(d->type, TABLE_TIMESTAMP_RELATIVE, TABLE_TIMESTAMP_LEFT) ?
|
||||
IN_SET(d->type, TABLE_TIMESTAMP_RELATIVE, TABLE_TIMESTAMP_RELATIVE_MONOTONIC, TABLE_TIMESTAMP_LEFT) ?
|
||||
FORMAT_TIMESTAMP_RELATIVE_MAX : FORMAT_TIMESTAMP_MAX);
|
||||
if (!p)
|
||||
return NULL;
|
||||
@ -1581,10 +1585,14 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
|
||||
ret = format_timestamp_style(p, FORMAT_TIMESTAMP_MAX, d->timestamp, TIMESTAMP_UTC);
|
||||
else if (d->type == TABLE_TIMESTAMP_DATE)
|
||||
ret = format_timestamp_style(p, FORMAT_TIMESTAMP_MAX, d->timestamp, TIMESTAMP_DATE);
|
||||
else if (d->type == TABLE_TIMESTAMP_RELATIVE_MONOTONIC)
|
||||
ret = format_timestamp_relative_full(p, FORMAT_TIMESTAMP_RELATIVE_MAX,
|
||||
d->timestamp, CLOCK_MONOTONIC,
|
||||
/* implicit_left = */ false);
|
||||
else
|
||||
ret = format_timestamp_relative_full(
|
||||
p, FORMAT_TIMESTAMP_RELATIVE_MAX, d->timestamp,
|
||||
/* implicit_left= */ d->type == TABLE_TIMESTAMP_LEFT);
|
||||
ret = format_timestamp_relative_full(p, FORMAT_TIMESTAMP_RELATIVE_MAX,
|
||||
d->timestamp, CLOCK_REALTIME,
|
||||
/* implicit_left = */ d->type == TABLE_TIMESTAMP_LEFT);
|
||||
if (!ret)
|
||||
return "-";
|
||||
|
||||
@ -2640,6 +2648,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_RELATIVE_MONOTONIC:
|
||||
case TABLE_TIMESTAMP_LEFT:
|
||||
case TABLE_TIMESTAMP_DATE:
|
||||
if (d->timestamp == USEC_INFINITY)
|
||||
|
@ -23,6 +23,7 @@ typedef enum TableDataType {
|
||||
TABLE_TIMESTAMP,
|
||||
TABLE_TIMESTAMP_UTC,
|
||||
TABLE_TIMESTAMP_RELATIVE,
|
||||
TABLE_TIMESTAMP_RELATIVE_MONOTONIC,
|
||||
TABLE_TIMESTAMP_LEFT,
|
||||
TABLE_TIMESTAMP_DATE,
|
||||
TABLE_TIMESPAN,
|
||||
|
@ -536,9 +536,10 @@ static int get_next_elapse(
|
||||
static int get_last_trigger(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
usec_t *last) {
|
||||
dual_timestamp *last) {
|
||||
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
dual_timestamp t;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
@ -553,10 +554,23 @@ static int get_last_trigger(
|
||||
"LastTriggerUSec",
|
||||
&error,
|
||||
't',
|
||||
last);
|
||||
&t.realtime);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get last trigger time: %s", bus_error_message(&error, r));
|
||||
|
||||
r = sd_bus_get_property_trivial(
|
||||
bus,
|
||||
"org.freedesktop.systemd1",
|
||||
path,
|
||||
"org.freedesktop.systemd1.Timer",
|
||||
"LastTriggerUSecMonotonic",
|
||||
&error,
|
||||
't',
|
||||
&t.monotonic);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get last trigger time: %s", bus_error_message(&error, r));
|
||||
|
||||
*last = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -564,7 +578,7 @@ typedef struct TimerInfo {
|
||||
const char* machine;
|
||||
const char* id;
|
||||
usec_t next_elapse;
|
||||
usec_t last_trigger;
|
||||
dual_timestamp last_trigger;
|
||||
char **triggered;
|
||||
} TimerInfo;
|
||||
|
||||
@ -623,8 +637,8 @@ static int output_timers_list(const TimerInfo *timers, size_t n_timers) {
|
||||
r = table_add_many(table,
|
||||
TABLE_TIMESTAMP, t->next_elapse,
|
||||
TABLE_TIMESTAMP_LEFT, t->next_elapse,
|
||||
TABLE_TIMESTAMP, t->last_trigger,
|
||||
TABLE_TIMESTAMP_RELATIVE, t->last_trigger,
|
||||
TABLE_TIMESTAMP, t->last_trigger.realtime,
|
||||
TABLE_TIMESTAMP_RELATIVE_MONOTONIC, t->last_trigger.monotonic,
|
||||
TABLE_STRING, unit);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
@ -677,8 +691,8 @@ static int add_timer_info(
|
||||
size_t *n_timers) {
|
||||
|
||||
_cleanup_strv_free_ char **triggered = NULL;
|
||||
dual_timestamp next = DUAL_TIMESTAMP_NULL;
|
||||
usec_t m, last = 0;
|
||||
dual_timestamp next, last;
|
||||
usec_t m;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
|
@ -464,64 +464,69 @@ TEST(format_timestamp_relative_full) {
|
||||
|
||||
/* 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));
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, CLOCK_REALTIME, true));
|
||||
log_debug("%s", buf);
|
||||
assert_se(streq(buf, "1 year 1 month ago"));
|
||||
|
||||
x = now(CLOCK_MONOTONIC) + (1*USEC_PER_YEAR + 1.5*USEC_PER_MONTH);
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, CLOCK_MONOTONIC, false));
|
||||
log_debug("%s", buf);
|
||||
assert_se(streq(buf, "1 year 1 month left"));
|
||||
|
||||
x = now(CLOCK_REALTIME) - (1*USEC_PER_YEAR + 2*USEC_PER_MONTH);
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, true));
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, CLOCK_REALTIME, 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));
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, CLOCK_REALTIME, 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));
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, CLOCK_REALTIME, 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));
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, CLOCK_REALTIME, 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));
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, CLOCK_REALTIME, 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));
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, CLOCK_REALTIME, 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));
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, CLOCK_REALTIME, 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));
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, CLOCK_REALTIME, 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));
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, CLOCK_REALTIME, 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));
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, CLOCK_REALTIME, 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));
|
||||
assert_se(format_timestamp_relative_full(buf, sizeof(buf), x, CLOCK_REALTIME, true));
|
||||
log_debug("%s", buf);
|
||||
assert_se(streq(buf, "2 weeks 2 days ago"));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user