mirror of
https://github.com/systemd/systemd.git
synced 2025-03-08 08:58:27 +03:00
parent
a8b7e8a742
commit
d80e5b74e8
@ -487,22 +487,33 @@ static int parse_weekdays(const char **p, CalendarSpec *c) {
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_one_number(const char *p, const char **e, unsigned long *ret) {
|
||||
char *ee = NULL;
|
||||
unsigned long value;
|
||||
|
||||
errno = 0;
|
||||
value = strtoul(p, &ee, 10);
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
if (ee == p)
|
||||
return -EINVAL;
|
||||
|
||||
*ret = value;
|
||||
*e = ee;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_component_decimal(const char **p, bool usec, int *res) {
|
||||
unsigned long value;
|
||||
const char *e = NULL;
|
||||
char *ee = NULL;
|
||||
int r;
|
||||
|
||||
if (!isdigit(**p))
|
||||
return -EINVAL;
|
||||
|
||||
errno = 0;
|
||||
value = strtoul(*p, &ee, 10);
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
if (ee == *p)
|
||||
return -EINVAL;
|
||||
e = ee;
|
||||
r = parse_one_number(*p, &e, &value);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (usec) {
|
||||
if (value * USEC_PER_SEC / USEC_PER_SEC != value)
|
||||
@ -553,6 +564,47 @@ static int const_chain(int value, CalendarComponent **c) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int calendarspec_from_time_t(CalendarSpec *c, time_t time) {
|
||||
struct tm tm;
|
||||
CalendarComponent *year = NULL, *month = NULL, *day = NULL, *hour = NULL, *minute = NULL, *us = NULL;
|
||||
int r;
|
||||
|
||||
assert_se(gmtime_r(&time, &tm));
|
||||
|
||||
r = const_chain(tm.tm_year + 1900, &year);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = const_chain(tm.tm_mon + 1, &month);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = const_chain(tm.tm_mday, &day);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = const_chain(tm.tm_hour, &hour);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = const_chain(tm.tm_min, &minute);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = const_chain(tm.tm_sec * USEC_PER_SEC, &us);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
c->utc = true;
|
||||
c->year = year;
|
||||
c->month = month;
|
||||
c->day = day;
|
||||
c->hour = hour;
|
||||
c->minute = minute;
|
||||
c->microsecond = us;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prepend_component(const char **p, bool usec, CalendarComponent **c) {
|
||||
int r, start, stop = -1, repeat = 0;
|
||||
CalendarComponent *cc;
|
||||
@ -657,6 +709,27 @@ static int parse_date(const char **p, CalendarSpec *c) {
|
||||
if (*t == 0)
|
||||
return 0;
|
||||
|
||||
/* @TIMESTAMP — UNIX time in seconds since the epoch */
|
||||
if (*t == '@') {
|
||||
unsigned long value;
|
||||
time_t time;
|
||||
|
||||
r = parse_one_number(t + 1, &t, &value);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
time = value;
|
||||
if ((unsigned long) time != value)
|
||||
return -ERANGE;
|
||||
|
||||
r = calendarspec_from_time_t(c, time);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*p = t;
|
||||
return 1; /* finito, don't parse H:M:S after that */
|
||||
}
|
||||
|
||||
r = parse_chain(&t, false, &first);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -832,7 +905,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
|
||||
continue;
|
||||
|
||||
e = endswith_no_case(p, tzname[j]);
|
||||
if(!e)
|
||||
if (!e)
|
||||
continue;
|
||||
if (e == p)
|
||||
continue;
|
||||
@ -986,9 +1059,11 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = parse_calendar_time(&p, c);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
if (r == 0) {
|
||||
r = parse_calendar_time(&p, c);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (*p != 0) {
|
||||
r = -EINVAL;
|
||||
|
@ -193,6 +193,11 @@ int main(int argc, char* argv[]) {
|
||||
test_one("*:20..39/5", "*-*-* *:20..35/5:00");
|
||||
test_one("00:00:20..40/1", "*-*-* 00:00:20..40");
|
||||
test_one("*~03/1,03..05", "*-*~03/1,03..05 00:00:00");
|
||||
/* UNIX timestamps are always UTC */
|
||||
test_one("@1493187147", "2017-04-26 06:12:27 UTC");
|
||||
test_one("@1493187147 UTC", "2017-04-26 06:12:27 UTC");
|
||||
test_one("@0", "1970-01-01 00:00:00 UTC");
|
||||
test_one("@0 UTC", "1970-01-01 00:00:00 UTC");
|
||||
|
||||
test_next("2016-03-27 03:17:00", "", 12345, 1459048620000000);
|
||||
test_next("2016-03-27 03:17:00", "CET", 12345, 1459041420000000);
|
||||
|
@ -29,7 +29,7 @@ static void test_should_pass(const char *p) {
|
||||
|
||||
assert_se(parse_timestamp(p, &t) >= 0);
|
||||
format_timestamp_us(buf, sizeof(buf), t);
|
||||
log_info("%s", buf);
|
||||
log_info("\"%s\" → \"%s\"", p, buf);
|
||||
|
||||
/* Chop off timezone */
|
||||
sp = strrchr(buf, ' ');
|
||||
|
Loading…
x
Reference in New Issue
Block a user