]>
Commit | Line | Data |
---|---|---|
5229b03c LP |
1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | ||
3 | #include "analyze.h" | |
4 | #include "analyze-calendar.h" | |
5 | #include "calendarspec.h" | |
6 | #include "format-table.h" | |
7 | #include "terminal-util.h" | |
8 | ||
9 | static int test_calendar_one(usec_t n, const char *p) { | |
10 | _cleanup_(calendar_spec_freep) CalendarSpec *spec = NULL; | |
11 | _cleanup_(table_unrefp) Table *table = NULL; | |
12 | _cleanup_free_ char *t = NULL; | |
13 | TableCell *cell; | |
14 | int r; | |
15 | ||
16 | r = calendar_spec_from_string(p, &spec); | |
17 | if (r < 0) { | |
18 | log_error_errno(r, "Failed to parse calendar specification '%s': %m", p); | |
19 | time_parsing_hint(p, /* calendar= */ false, /* timestamp= */ true, /* timespan= */ true); | |
20 | return r; | |
21 | } | |
22 | ||
23 | r = calendar_spec_to_string(spec, &t); | |
24 | if (r < 0) | |
25 | return log_error_errno(r, "Failed to format calendar specification '%s': %m", p); | |
26 | ||
f607ebca | 27 | table = table_new_vertical(); |
5229b03c LP |
28 | if (!table) |
29 | return log_oom(); | |
30 | ||
5229b03c LP |
31 | assert_se(cell = table_get_cell(table, 0, 0)); |
32 | r = table_set_ellipsize_percent(table, cell, 100); | |
33 | if (r < 0) | |
34 | return r; | |
35 | ||
5229b03c LP |
36 | assert_se(cell = table_get_cell(table, 0, 1)); |
37 | r = table_set_ellipsize_percent(table, cell, 100); | |
38 | if (r < 0) | |
39 | return r; | |
40 | ||
41 | if (!streq(t, p)) { | |
42 | r = table_add_many(table, | |
f607ebca | 43 | TABLE_FIELD, "Original form", |
5229b03c LP |
44 | TABLE_STRING, p); |
45 | if (r < 0) | |
46 | return table_log_add_error(r); | |
47 | } | |
48 | ||
49 | r = table_add_many(table, | |
f607ebca | 50 | TABLE_FIELD, "Normalized form", |
5229b03c LP |
51 | TABLE_STRING, t); |
52 | if (r < 0) | |
53 | return table_log_add_error(r); | |
54 | ||
55 | for (unsigned i = 0; i < arg_iterations; i++) { | |
56 | usec_t next; | |
57 | ||
58 | r = calendar_spec_next_usec(spec, n, &next); | |
59 | if (r == -ENOENT) { | |
60 | if (i == 0) { | |
61 | r = table_add_many(table, | |
f607ebca | 62 | TABLE_FIELD, "Next elapse", |
5229b03c LP |
63 | TABLE_STRING, "never", |
64 | TABLE_SET_COLOR, ansi_highlight_yellow()); | |
65 | if (r < 0) | |
66 | return table_log_add_error(r); | |
67 | } | |
68 | break; | |
69 | } | |
70 | if (r < 0) | |
71 | return log_error_errno(r, "Failed to determine next elapse for '%s': %m", p); | |
72 | ||
73 | if (i == 0) { | |
74 | r = table_add_many(table, | |
f607ebca | 75 | TABLE_FIELD, "Next elapse", |
5229b03c LP |
76 | TABLE_TIMESTAMP, next, |
77 | TABLE_SET_COLOR, ansi_highlight_blue()); | |
78 | if (r < 0) | |
79 | return table_log_add_error(r); | |
80 | } else { | |
81 | int k = DECIMAL_STR_WIDTH(i + 1); | |
82 | ||
83 | if (k < 8) | |
84 | k = 8 - k; | |
85 | else | |
86 | k = 0; | |
87 | ||
f607ebca | 88 | r = table_add_cell_stringf_full(table, NULL, TABLE_FIELD, "Iteration #%u", i+1); |
5229b03c LP |
89 | if (r < 0) |
90 | return table_log_add_error(r); | |
91 | ||
92 | r = table_add_many(table, | |
93 | TABLE_TIMESTAMP, next, | |
94 | TABLE_SET_COLOR, ansi_highlight_blue()); | |
95 | if (r < 0) | |
96 | return table_log_add_error(r); | |
97 | } | |
98 | ||
99 | if (!in_utc_timezone()) { | |
100 | r = table_add_many(table, | |
f607ebca | 101 | TABLE_FIELD, "(in UTC)", |
5229b03c LP |
102 | TABLE_TIMESTAMP_UTC, next); |
103 | if (r < 0) | |
104 | return table_log_add_error(r); | |
105 | } | |
106 | ||
107 | r = table_add_many(table, | |
f607ebca | 108 | TABLE_FIELD, "From now", |
5229b03c LP |
109 | TABLE_TIMESTAMP_RELATIVE, next); |
110 | if (r < 0) | |
111 | return table_log_add_error(r); | |
112 | ||
113 | n = next; | |
114 | } | |
115 | ||
116 | return table_print(table, NULL); | |
117 | } | |
118 | ||
ef38bedb | 119 | int verb_calendar(int argc, char *argv[], void *userdata) { |
fddad5f4 | 120 | int r = 0; |
5229b03c LP |
121 | usec_t n; |
122 | ||
123 | if (arg_base_time != USEC_INFINITY) | |
124 | n = arg_base_time; | |
125 | else | |
126 | n = now(CLOCK_REALTIME); /* We want to use the same "base" for all expressions */ | |
127 | ||
128 | STRV_FOREACH(p, strv_skip(argv, 1)) { | |
fddad5f4 | 129 | int k; |
5229b03c | 130 | |
fddad5f4 ZJS |
131 | k = test_calendar_one(n, *p); |
132 | if (r == 0 && k < 0) | |
133 | r = k; | |
134 | ||
135 | if (p[1]) | |
5229b03c LP |
136 | putchar('\n'); |
137 | } | |
138 | ||
fddad5f4 | 139 | return r; |
5229b03c | 140 | } |