basic: parse_timestamp UTC and fractional seconds support
This commit is contained in:
parent
7c67c79c9a
commit
e4eaf99a31
|
@ -477,9 +477,10 @@ int parse_timestamp(const char *t, usec_t *usec) {
|
|||
};
|
||||
|
||||
const char *k;
|
||||
bool utc;
|
||||
struct tm tm, copy;
|
||||
time_t x;
|
||||
usec_t plus = 0, minus = 0, ret;
|
||||
usec_t x_usec, plus = 0, minus = 0, ret;
|
||||
int r, weekday = -1;
|
||||
unsigned i;
|
||||
|
||||
|
@ -504,28 +505,15 @@ int parse_timestamp(const char *t, usec_t *usec) {
|
|||
assert(t);
|
||||
assert(usec);
|
||||
|
||||
x = time(NULL);
|
||||
assert_se(localtime_r(&x, &tm));
|
||||
tm.tm_isdst = -1;
|
||||
if (t[0] == '@')
|
||||
return parse_sec(t + 1, usec);
|
||||
|
||||
ret = now(CLOCK_REALTIME);
|
||||
|
||||
if (streq(t, "now"))
|
||||
goto finish;
|
||||
|
||||
else if (streq(t, "today")) {
|
||||
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
|
||||
goto finish;
|
||||
|
||||
} else if (streq(t, "yesterday")) {
|
||||
tm.tm_mday --;
|
||||
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
|
||||
goto finish;
|
||||
|
||||
} else if (streq(t, "tomorrow")) {
|
||||
tm.tm_mday ++;
|
||||
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
|
||||
goto finish;
|
||||
|
||||
} else if (t[0] == '+') {
|
||||
else if (t[0] == '+') {
|
||||
r = parse_sec(t+1, &plus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -539,35 +527,51 @@ int parse_timestamp(const char *t, usec_t *usec) {
|
|||
|
||||
goto finish;
|
||||
|
||||
} else if (t[0] == '@')
|
||||
return parse_sec(t + 1, usec);
|
||||
} else if (endswith(t, " ago")) {
|
||||
t = strndupa(t, strlen(t) - strlen(" ago"));
|
||||
|
||||
else if (endswith(t, " ago")) {
|
||||
_cleanup_free_ char *z;
|
||||
|
||||
z = strndup(t, strlen(t) - 4);
|
||||
if (!z)
|
||||
return -ENOMEM;
|
||||
|
||||
r = parse_sec(z, &minus);
|
||||
r = parse_sec(t, &minus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
goto finish;
|
||||
|
||||
} else if (endswith(t, " left")) {
|
||||
_cleanup_free_ char *z;
|
||||
t = strndupa(t, strlen(t) - strlen(" left"));
|
||||
|
||||
z = strndup(t, strlen(t) - 4);
|
||||
if (!z)
|
||||
return -ENOMEM;
|
||||
|
||||
r = parse_sec(z, &plus);
|
||||
r = parse_sec(t, &plus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
goto finish;
|
||||
}
|
||||
|
||||
utc = endswith_no_case(t, " UTC");
|
||||
if (utc)
|
||||
t = strndupa(t, strlen(t) - strlen(" UTC"));
|
||||
|
||||
x = ret / USEC_PER_SEC;
|
||||
x_usec = 0;
|
||||
|
||||
assert_se(localtime_or_gmtime_r(&x, &tm, utc));
|
||||
tm.tm_isdst = -1;
|
||||
|
||||
if (streq(t, "today")) {
|
||||
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
|
||||
goto from_tm;
|
||||
|
||||
} else if (streq(t, "yesterday")) {
|
||||
tm.tm_mday --;
|
||||
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
|
||||
goto from_tm;
|
||||
|
||||
} else if (streq(t, "tomorrow")) {
|
||||
tm.tm_mday ++;
|
||||
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
|
||||
goto from_tm;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(day_nr); i++) {
|
||||
size_t skip;
|
||||
|
||||
|
@ -585,66 +589,106 @@ int parse_timestamp(const char *t, usec_t *usec) {
|
|||
|
||||
copy = tm;
|
||||
k = strptime(t, "%y-%m-%d %H:%M:%S", &tm);
|
||||
if (k && *k == 0)
|
||||
goto finish;
|
||||
if (k) {
|
||||
if (*k == '.')
|
||||
goto parse_usec;
|
||||
else if (*k == 0)
|
||||
goto from_tm;
|
||||
}
|
||||
|
||||
tm = copy;
|
||||
k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm);
|
||||
if (k && *k == 0)
|
||||
goto finish;
|
||||
if (k) {
|
||||
if (*k == '.')
|
||||
goto parse_usec;
|
||||
else if (*k == 0)
|
||||
goto from_tm;
|
||||
}
|
||||
|
||||
tm = copy;
|
||||
k = strptime(t, "%y-%m-%d %H:%M", &tm);
|
||||
if (k && *k == 0) {
|
||||
tm.tm_sec = 0;
|
||||
goto finish;
|
||||
goto from_tm;
|
||||
}
|
||||
|
||||
tm = copy;
|
||||
k = strptime(t, "%Y-%m-%d %H:%M", &tm);
|
||||
if (k && *k == 0) {
|
||||
tm.tm_sec = 0;
|
||||
goto finish;
|
||||
goto from_tm;
|
||||
}
|
||||
|
||||
tm = copy;
|
||||
k = strptime(t, "%y-%m-%d", &tm);
|
||||
if (k && *k == 0) {
|
||||
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
|
||||
goto finish;
|
||||
goto from_tm;
|
||||
}
|
||||
|
||||
tm = copy;
|
||||
k = strptime(t, "%Y-%m-%d", &tm);
|
||||
if (k && *k == 0) {
|
||||
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
|
||||
goto finish;
|
||||
goto from_tm;
|
||||
}
|
||||
|
||||
tm = copy;
|
||||
k = strptime(t, "%H:%M:%S", &tm);
|
||||
if (k && *k == 0)
|
||||
goto finish;
|
||||
if (k) {
|
||||
if (*k == '.')
|
||||
goto parse_usec;
|
||||
else if (*k == 0)
|
||||
goto from_tm;
|
||||
}
|
||||
|
||||
tm = copy;
|
||||
k = strptime(t, "%H:%M", &tm);
|
||||
if (k && *k == 0) {
|
||||
tm.tm_sec = 0;
|
||||
goto finish;
|
||||
goto from_tm;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
|
||||
finish:
|
||||
x = mktime(&tm);
|
||||
parse_usec:
|
||||
{
|
||||
char *end;
|
||||
unsigned long long val;
|
||||
size_t l;
|
||||
|
||||
k++;
|
||||
if (*k < '0' || *k > '9')
|
||||
return -EINVAL;
|
||||
|
||||
/* base 10 instead of base 0, .09 is not base 8 */
|
||||
errno = 0;
|
||||
val = strtoull(k, &end, 10);
|
||||
if (*end || errno)
|
||||
return -EINVAL;
|
||||
|
||||
l = end-k;
|
||||
|
||||
/* val has l digits, make them 6 */
|
||||
for (; l < 6; l++)
|
||||
val *= 10;
|
||||
for (; l > 6; l--)
|
||||
val /= 10;
|
||||
|
||||
x_usec = val;
|
||||
}
|
||||
|
||||
from_tm:
|
||||
x = mktime_or_timegm(&tm, utc);
|
||||
if (x == (time_t) -1)
|
||||
return -EINVAL;
|
||||
|
||||
if (weekday >= 0 && tm.tm_wday != weekday)
|
||||
return -EINVAL;
|
||||
|
||||
ret = (usec_t) x * USEC_PER_SEC;
|
||||
ret = (usec_t) x * USEC_PER_SEC + x_usec;
|
||||
|
||||
finish:
|
||||
ret += plus;
|
||||
if (ret > minus)
|
||||
ret -= minus;
|
||||
|
|
Loading…
Reference in a new issue