diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml
index 7aa10fc68e2..15e95b0c8f5 100644
--- a/man/systemd-analyze.xml
+++ b/man/systemd-analyze.xml
@@ -106,6 +106,12 @@
service-watchdogs
BOOL
+
+ systemd-analyze
+ OPTIONS
+ timespan
+ SPAN
+
@@ -253,6 +259,10 @@ NAutoVTs=8
systemd.service5.
The hardware watchdog is not affected by this setting.
+ systemd-analyze timespan parses a time span and outputs the equivalent value in microseconds, and as a reformatted timespan.
+ The time span should adhere to the same syntax documented in systemd.time7.
+ Values without associated magnitudes are parsed as seconds.
+
If no command is passed, systemd-analyze
time is implied.
diff --git a/man/systemd.time.xml b/man/systemd.time.xml
index 15e1680b8db..24df5ab9429 100644
--- a/man/systemd.time.xml
+++ b/man/systemd.time.xml
@@ -74,6 +74,10 @@
1y 12month
55s500ms
300ms20s 5day
+
+ One can use the timespan command of
+ systemd-analyze1
+ to normalise a textual time span for testing and validation purposes.
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 144f18e9c72..d381740dfb4 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -4,6 +4,7 @@
***/
#include
+#include
#include
#include
#include
@@ -33,6 +34,7 @@
#include "special.h"
#include "strv.h"
#include "strxcpyx.h"
+#include "time-util.h"
#include "terminal-util.h"
#include "unit-name.h"
#include "util.h"
@@ -1551,6 +1553,29 @@ static int dump_syscall_filters(int argc, char *argv[], void *userdata) {
}
#endif
+static int dump_timespan(int argc, char *argv[], void *userdata) {
+ char **input_timespan;
+
+ STRV_FOREACH(input_timespan, strv_skip(argv, 1)) {
+ int r;
+ usec_t usec_magnitude = 1, output_usecs;
+ char ft_buf[FORMAT_TIMESPAN_MAX];
+
+ r = parse_time(*input_timespan, &output_usecs, USEC_PER_SEC);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse time span '%s': %m", *input_timespan);
+
+ printf("Original: %s\n", *input_timespan);
+ printf(" %ss: %" PRIu64 "\n", special_glyph(MU), output_usecs);
+ printf(" Human: %s\n", format_timespan(ft_buf, sizeof(ft_buf), output_usecs, usec_magnitude));
+
+ if (input_timespan[1])
+ putchar('\n');
+ }
+
+ return EXIT_SUCCESS;
+}
+
static int test_calendar(int argc, char *argv[], void *userdata) {
int ret = 0, r;
char **p;
@@ -1710,6 +1735,7 @@ static int help(int argc, char *argv[], void *userdata) {
" verify FILE... Check unit files for correctness\n"
" calendar SPEC... Validate repetitive calendar time events\n"
" service-watchdogs [BOOL] Get/set service watchdog state\n"
+ " timespan SPAN... Validate a time span\n"
"\nSee the %s for details.\n"
, program_invocation_short_name
, link
@@ -1900,6 +1926,7 @@ int main(int argc, char *argv[]) {
{ "verify", 2, VERB_ANY, 0, do_verify },
{ "calendar", 2, VERB_ANY, 0, test_calendar },
{ "service-watchdogs", VERB_ANY, 2, 0, service_watchdogs },
+ { "timespan", 2, VERB_ANY, 0, dump_timespan },
{}
};
diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c
index 3ad352f22f3..8b89bd00244 100644
--- a/src/basic/locale-util.c
+++ b/src/basic/locale-util.c
@@ -367,7 +367,8 @@ const char *special_glyph(SpecialGlyph code) {
[BLACK_CIRCLE] = "*",
[ARROW] = "->",
[MDASH] = "-",
- [ELLIPSIS] = "..."
+ [ELLIPSIS] = "...",
+ [MU] = "u",
},
/* UTF-8 */
@@ -381,6 +382,7 @@ const char *special_glyph(SpecialGlyph code) {
[ARROW] = "\342\206\222", /* → */
[MDASH] = "\342\200\223", /* – */
[ELLIPSIS] = "\342\200\246", /* … */
+ [MU] = "\316\274", /* μ */
},
};
diff --git a/src/basic/locale-util.h b/src/basic/locale-util.h
index 775fe8bc728..7762254940d 100644
--- a/src/basic/locale-util.h
+++ b/src/basic/locale-util.h
@@ -48,6 +48,7 @@ typedef enum {
ARROW,
MDASH,
ELLIPSIS,
+ MU,
_SPECIAL_GLYPH_MAX
} SpecialGlyph;
diff --git a/src/test/test-locale-util.c b/src/test/test-locale-util.c
index 8ffae8ca03d..3634534782d 100644
--- a/src/test/test-locale-util.c
+++ b/src/test/test-locale-util.c
@@ -65,7 +65,7 @@ static void test_keymaps(void) {
#define dump_glyph(x) log_info(STRINGIFY(x) ": %s", special_glyph(x))
static void dump_special_glyphs(void) {
- assert_cc(ELLIPSIS + 1 == _SPECIAL_GLYPH_MAX);
+ assert_cc(MU + 1 == _SPECIAL_GLYPH_MAX);
log_info("/* %s */", __func__);