From 79dc2434cb8d39213b24b89f6c618174d8e9cbd4 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 24 Mar 2019 18:05:34 -0500 Subject: Factor out xparsedate() and xvali_date() into lib. --- lib/lib.h | 2 ++ lib/xwrap.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) (limited to 'lib') diff --git a/lib/lib.h b/lib/lib.h index 599ade06..174c1fd6 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -181,6 +181,8 @@ void xregcomp(regex_t *preg, char *rexec, int cflags); char *xtzset(char *new); void xsignal_flags(int signal, void *handler, int flags); void xsignal(int signal, void *handler); +time_t xvali_date(struct tm *tm, char *str); +void xparsedate(char *str, time_t *t, unsigned *nano); // lib.c void verror_msg(char *msg, int err, va_list va); diff --git a/lib/xwrap.c b/lib/xwrap.c index c133125a..ee07fda2 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -944,3 +944,111 @@ void xsignal(int signal, void *handler) { xsignal_flags(signal, handler, 0); } + + +time_t xvali_date(struct tm *tm, char *str) +{ + time_t t; + + if (tm && (unsigned)tm->tm_sec<=60 && (unsigned)tm->tm_min<=59 + && (unsigned)tm->tm_hour<=23 && tm->tm_mday && (unsigned)tm->tm_mday<=31 + && (unsigned)tm->tm_mon<=11 && (t = mktime(tm)) != -1) return t; + + error_exit("bad date %s", str); +} + +// Parse date string (relative to current *t). Sets time_t and nanoseconds. +void xparsedate(char *str, time_t *t, unsigned *nano) +{ + struct tm tm; + time_t now = *t; + int len = 0, i; + // Formats with years must come first. + char *s = str, *p, *formats[] = {"%F %T", "%FT%T", "%F %H:%M", "%F", + "%H:%M:%S", "%H:%M"}; + + *nano = 0; + + // Parse @UNIXTIME[.FRACTION] + if (*str == '@') { + long long ll; + + // Collect seconds and nanoseconds. + // &ll is not just t because we can't guarantee time_t is 64 bit (yet). + sscanf(s, "@%lld%n", &ll, &len); + if (s[len]=='.') { + s += len+1; + for (len = 0; len<9; len++) { + *nano *= 10; + if (isdigit(*s)) *nano += *s++-'0'; + } + } + if (s[len]) goto bad_dates; + *t = ll; + + return; + } + + // Is it one of the fancy formats? + for (i = 0; i r2)) { + if (year < r1) year += 100; + } else if (year > r1) year -= 100; + tm.tm_year = year + century; + } + } + // Fractional part? + if (*s == '.') { + len = 0; + sscanf(s, ".%2u%n", &tm.tm_sec, &len); + s += len; + for (len = 0; len<9; len++) { + *nano *= 10; + if (isdigit(*s)) *nano += *s++-'0'; + } + } else tm.tm_sec = 0; + + // Sanity check field ranges + *t = xvali_date(&tm, str); + + // Shouldn't be any trailing garbage. + if (!*s) return; + +bad_dates: + // monkey died + xvali_date(0, str); +} -- cgit v1.2.3