mirror of
https://github.com/systemd/systemd.git
synced 2025-01-23 02:04:32 +03:00
calendarspec: allow ranges in date and time specifications
Resolves #3042
This commit is contained in:
parent
563a69f480
commit
32b5236916
1
TODO
1
TODO
@ -565,7 +565,6 @@ Features:
|
||||
o CLOCK_REALTIME makes jumps (TFD_TIMER_CANCEL_ON_SET)
|
||||
o DST changes
|
||||
- Support 2012-02~4 as syntax for specifying the fourth to last day of the month.
|
||||
- calendarspec: support value ranges with ".." notation. Example: 2013-4..8-1
|
||||
- Modulate timer frequency based on battery state
|
||||
|
||||
* add libsystemd-password or so to query passwords during boot using the password agent logic
|
||||
|
@ -227,7 +227,8 @@
|
||||
values separated by commas. Values may also be suffixed with
|
||||
<literal>/</literal> and a repetition value, which indicates that
|
||||
the value and all values plus multiples of the repetition value
|
||||
are matched.</para>
|
||||
are matched. Each component may also contain a range of values
|
||||
separated by <literal>..</literal>.</para>
|
||||
|
||||
<para>The seconds component may contain decimal fractions both in
|
||||
the value and the repetition. All fractions are rounded to 6
|
||||
@ -273,6 +274,7 @@ Wed-Sat,Tue 12-10-15 1:2:3 → Tue-Sat 2012-10-15 01:02:03
|
||||
monday *-12-* 17:00 → Mon *-12-* 17:00:00
|
||||
Mon,Fri *-*-3,1,2 *:30:45 → Mon,Fri *-*-01,02,03 *:30:45
|
||||
12,14,13,12:20,10,30 → *-*-* 12,13,14:10,20,30:00
|
||||
12..14:10,20,30 → *-*-* 12,13,14:10,20,30:00
|
||||
mon,fri *-1/2-1,3 *:30:45 → Mon,Fri *-01/2-01,03 *:30:45
|
||||
03-05 08:05:40 → *-03-05 08:05:40
|
||||
08:05:40 → *-*-* 08:05:40
|
||||
@ -281,6 +283,7 @@ Wed-Sat,Tue 12-10-15 1:2:3 → Tue-Sat 2012-10-15 01:02:03
|
||||
Sat,Sun 08:05:40 → Sat,Sun *-*-* 08:05:40
|
||||
2003-03-05 05:40 → 2003-03-05 05:40:00
|
||||
05:40:23.4200004/3.1700005 → 05:40:23.420000/3.170001
|
||||
2003-02..04-05 → 2003-02,03,04-05 00:00:00
|
||||
2003-03-05 05:40 UTC → 2003-03-05 05:40:00 UTC
|
||||
2003-03-05 → 2003-03-05 00:00:00
|
||||
03-05 → *-03-05 00:00:00
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include "parse-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
/* Longest valid date/time range is 1970..2199 */
|
||||
#define MAX_RANGE_LEN 230
|
||||
#define BITS_WEEKDAYS 127
|
||||
|
||||
static void free_chain(CalendarComponent *c) {
|
||||
@ -448,8 +450,26 @@ static int parse_component_decimal(const char **p, bool usec, unsigned long *res
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int const_chain(int value, CalendarComponent **c) {
|
||||
CalendarComponent *cc = NULL;
|
||||
|
||||
assert(c);
|
||||
|
||||
cc = new0(CalendarComponent, 1);
|
||||
if (!cc)
|
||||
return -ENOMEM;
|
||||
|
||||
cc->value = value;
|
||||
cc->repeat = 0;
|
||||
cc->next = *c;
|
||||
|
||||
*c = cc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prepend_component(const char **p, bool usec, CalendarComponent **c) {
|
||||
unsigned long value, repeat = 0;
|
||||
unsigned long i, value, range_end, range_inc, repeat = 0;
|
||||
CalendarComponent *cc;
|
||||
int r;
|
||||
const char *e;
|
||||
@ -471,6 +491,30 @@ static int prepend_component(const char **p, bool usec, CalendarComponent **c) {
|
||||
|
||||
if (repeat == 0)
|
||||
return -ERANGE;
|
||||
} else if (e[0] == '.' && e[1] == '.') {
|
||||
e += 2;
|
||||
r = parse_component_decimal(&e, usec, &range_end);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (value >= range_end)
|
||||
return -EINVAL;
|
||||
|
||||
range_inc = usec ? USEC_PER_SEC : 1;
|
||||
|
||||
/* Don't allow impossibly large ranges... */
|
||||
if (range_end - value >= MAX_RANGE_LEN * range_inc)
|
||||
return -EINVAL;
|
||||
|
||||
/* ...or ranges with only a single element */
|
||||
if (range_end - value < range_inc)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = value; i <= range_end; i += range_inc) {
|
||||
r = const_chain(i, c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (*e != 0 && *e != ' ' && *e != ',' && *e != '-' && *e != ':')
|
||||
@ -495,24 +539,6 @@ static int prepend_component(const char **p, bool usec, CalendarComponent **c) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int const_chain(int value, CalendarComponent **c) {
|
||||
CalendarComponent *cc = NULL;
|
||||
|
||||
assert(c);
|
||||
|
||||
cc = new0(CalendarComponent, 1);
|
||||
if (!cc)
|
||||
return -ENOMEM;
|
||||
|
||||
cc->value = value;
|
||||
cc->repeat = 0;
|
||||
cc->next = *c;
|
||||
|
||||
*c = cc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_chain(const char **p, bool usec, CalendarComponent **c) {
|
||||
const char *t;
|
||||
CalendarComponent *cc = NULL;
|
||||
|
@ -124,6 +124,10 @@ int main(int argc, char* argv[]) {
|
||||
test_one("2016-03-27 03:17:00.4200005", "2016-03-27 03:17:00.420001");
|
||||
test_one("2016-03-27 03:17:00/0.42", "2016-03-27 03:17:00/0.420000");
|
||||
test_one("2016-03-27 03:17:00/0.42", "2016-03-27 03:17:00/0.420000");
|
||||
test_one("9..11,13:00,30", "*-*-* 09,10,11,13:00,30:00");
|
||||
test_one("1..3-1..3 1..3:1..3", "*-01,02,03-01,02,03 01,02,03:01,02,03:00");
|
||||
test_one("00:00:1.125..2.125", "*-*-* 00:00:01.125000,02.125000");
|
||||
test_one("00:00:1.0..3.8", "*-*-* 00:00:01,02,03");
|
||||
|
||||
test_next("2016-03-27 03:17:00", "", 12345, 1459048620000000);
|
||||
test_next("2016-03-27 03:17:00", "CET", 12345, 1459041420000000);
|
||||
@ -146,6 +150,7 @@ int main(int argc, char* argv[]) {
|
||||
assert_se(calendar_spec_from_string("2000-03-05.23 00:00:00", &c) < 0);
|
||||
assert_se(calendar_spec_from_string("2000-03-05 00:00.1:00", &c) < 0);
|
||||
assert_se(calendar_spec_from_string("00:00:00/0.00000001", &c) < 0);
|
||||
assert_se(calendar_spec_from_string("00:00:00.0..00.9", &c) < 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user