From 61954518994089b0b9f00e99c58dc100dd862769 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Tue, 21 Nov 2006 00:11:57 +0000 Subject: [PATCH] Use libiso8601 to parse the time. --- README | 4 +- src/mini-at/TopSource.c | 1 + src/mini-at/build.app | 3 +- src/mini-at/time.c | 418 +--------------------------------------- version | 4 +- 5 files changed, 13 insertions(+), 417 deletions(-) diff --git a/README b/README index 86b4c63..7399736 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -mini-at +mini-at http://www.lwithers.me.uk/projects/mini-at/ ======================================================================== (c)2006, Laurence Withers, . Released under the GNU GPLv2. See file COPYING or @@ -7,6 +7,8 @@ http://www.gnu.org/copyleft/gpl.html for details. Really Quick Instructions ------------------------- +Install libiso8601 from http://www.lwithers.me.uk/projects/libiso8601/ . + To build: ./make.sh To install: ./make.sh install (you might want to set PREFIX, by default it's /usr/local) diff --git a/src/mini-at/TopSource.c b/src/mini-at/TopSource.c index f215c82..f7a39eb 100644 --- a/src/mini-at/TopSource.c +++ b/src/mini-at/TopSource.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/src/mini-at/build.app b/src/mini-at/build.app index 064ba34..5e2be31 100644 --- a/src/mini-at/build.app +++ b/src/mini-at/build.app @@ -6,7 +6,8 @@ if [ -z ${mini_at_BUILT} ] then mini_at="obj/mini-at" - EXTRAS="" # @TODO@ cflags, libs + [ -z "${LIBISO8601_FLAGS}" ] && LIBISO8601_FLAGS="$(pkg-config libiso8601 --libs --cflags)" + EXTRAS="${LIBISO8601_FLAGS}" echo "Building application ${mini_at}..." diff --git a/src/mini-at/time.c b/src/mini-at/time.c index 7fe49df..055cd4d 100644 --- a/src/mini-at/time.c +++ b/src/mini-at/time.c @@ -7,426 +7,18 @@ -int parse_time_digs(const char* str, int numdigs) -{ - int i = 0; - char ch; - - while(numdigs--) { - switch( (ch = *str++) ) { - case '0' ... '9': - i *= 10; - i += ch - '0'; - break; - - default: - return -1; - } - } - - return i; -} - - - -int parse_time_date_daysinyear(int year) -{ - if(!(year % 400)) return 366; - if(!(year % 100)) return 365; - if(!(year % 4)) return 366; - return 365; -} - - - -struct parse_time_date_dayselapsed_t { - int ndays, elapsed; -}; - -struct parse_time_date_dayselapsed_t parse_time_date_dayselapsed_cal[] = { - { 31, 0 }, - { 28, 31 }, - { 31, 59 }, - { 30, 90 }, - { 31, 120 }, - { 30, 151 }, - { 31, 181 }, - { 31, 212 }, - { 30, 243 }, - { 31, 273 }, - { 30, 304 }, - { 31, 334 } -}; - -struct parse_time_date_dayselapsed_t parse_time_date_dayselapsed_leapcal[] = { - { 31, 0 }, - { 29, 31 }, - { 31, 60 }, - { 30, 91 }, - { 31, 121 }, - { 30, 152 }, - { 31, 182 }, - { 31, 213 }, - { 30, 244 }, - { 31, 274 }, - { 30, 305 }, - { 31, 335 } -}; - -int parse_time_date_dayselapsed(int year, int mon, int day) -{ - struct parse_time_date_dayselapsed_t* t; - - --mon; - if(mon < 0 || mon > 11) return -1; - - if(parse_time_date_daysinyear(year) == 366) t = parse_time_date_dayselapsed_leapcal; - else t = parse_time_date_dayselapsed_cal; - - t += mon; - --day; - if(day < 0 || day > t->ndays) return -1; - - return day + t->elapsed; -} - - - -// number of seconds elapsed between 1970 and start of `year' -time_t parse_time_date_mkyear(int year) -{ - long nd; - - // we have an inverse y2k problem! - // basically, the algorithm needs to operate on a 400-year boundary for leap days - // since this is `at', we don't deal with dates in the past - // time_t can't deal with dates earlier than 1970 - // so 2000 seems a logical place to start - year -= 2000; - if(year < 0) return -1; - - /* Every 4th year is leap - * unless it's a century (not leap) - * unless it's a 4*century (leap) - * - * So there are 97 leap days in 400 years, giving 365 * 400 + 397 = 146097 days - * For each 100 years, there are 24 leaps, giving 365 * 100 + 24 = 36524 days - * For each 4 years, there is 1 leap, giving 365 * 4 + 1 = 1461 days - */ - nd = 146097l * (year / 400); - year %= 400; - if(year) { - nd += 36524 * (year / 100); - year %= 100; - nd += 1461 * (year / 4); - if(year) { - year %= 4; - nd += (year ? 1 : 0) + 365 * year; - } else { - nd++; - } - } - - /* Now add number of days between 1970 and 2000 (7 leap years) - * 30 * 365 + 7 = 10957 */ - nd += 10957; - - // ignoring leap seconds, as time_t does, there are 86400 seconds in a day - nd *= 86400; - - // done! - return (time_t)nd; -} - - - -time_t parse_time_date_mkwk(int year, int wk, int wday) -{ -// time_t t; - - fprintf(stderr, "ISO8601 week dates not supported yet\n"); - return -1; - -/* - t = parse_time_date_mkyear(year); - if(t == (time_t)-1) return -1; -*/ -} - - - -time_t parse_time_date_mkord(int year, int oday) -{ - time_t t; - - if(oday < 1 || oday > parse_time_date_daysinyear(year)) return -1; - t = parse_time_date_mkyear(year); - if(t == (time_t)-1) return -1; - - t += (oday - 1) * 86400; - return t; -} - - - -time_t parse_time_date_mkcal(int year, int mon, int day) -{ - time_t t; - - t = parse_time_date_mkyear(year); - if(t == (time_t)-1) return -1; - - t += parse_time_date_dayselapsed(year, mon, day) * 86400; - return t; -} - - - -time_t parse_time_date(const char* str, const char* end) -{ - int year, mon, day; - const char* pos; - - // we don't deal with negative years -- this is at! - if(*str < '0' || *str > '9') return -1; - - if( (pos = strchr(str, 'W')) ) { - if(strchr(pos, '-')) { - /* Either of: - * yyyy-Www - * yyyy-Www-d - */ - switch(end - pos) { - case 3: - year = parse_time_digs(str, pos - str - 1); - mon = parse_time_digs(pos + 1, 2); - return parse_time_date_mkwk(year, mon, 1); - - case 5: - year = parse_time_digs(str, pos - str - 1); - mon = parse_time_digs(pos + 1, 2); - day = parse_time_digs(pos + 4, 1); - return parse_time_date_mkwk(year, mon, day); - - default: - return -1; - } - - } else { - /* Either of: - * yyyyWww - * yyyyWwwd - */ - switch(end - pos) { - case 3: - year = parse_time_digs(str, pos - str); - mon = parse_time_digs(pos + 1, 2); - return parse_time_date_mkwk(year, mon, 1); - - case 4: - year = parse_time_digs(str, pos - str); - mon = parse_time_digs(pos + 1, 2); - day = parse_time_digs(pos + 3, 2); - return parse_time_date_mkwk(year, mon, day); - - default: - return -1; - } - } - - } else if( (pos = strchr(str, '-')) ) { - /* Valid extended formats are: - * yyyy-mm (year + len 3) - * yyyy-ooo (year + len 4) - * yyyy-mm-dd (year + len 6) - */ - switch(end - pos) { - case 3: - year = parse_time_digs(str, pos - str); - mon = parse_time_digs(pos + 1, 2); - return parse_time_date_mkcal(year, mon, 1); - - case 4: - year = parse_time_digs(str, pos - str); - day = parse_time_digs(pos + 1, 3); - return parse_time_date_mkord(year, day); - - case 6: - year = parse_time_digs(str, pos - str); - mon = parse_time_digs(pos + 1, 2); - day = parse_time_digs(pos + 4, 2); - return parse_time_date_mkcal(year, mon, day); - - default: - return -1; - } - } - - /* Valid basic formats, excluding week formats, are: - * yyyy (len 4) - * yyyymm (len 6) - * yyyyooo (len 7) - * yyyymmdd (len 8) - */ - - switch(end - str) { - case 4: - year = parse_time_digs(str, 4); - return parse_time_date_mkord(year, 1); - - case 6: - year = parse_time_digs(str, 4); - mon = parse_time_digs(str + 4, 2); - return parse_time_date_mkcal(year, mon, 1); - - case 7: - year = parse_time_digs(str, 4); - day = parse_time_digs(str + 4, 3); - return parse_time_date_mkord(year, day); - - case 8: - year = parse_time_digs(str, 4); - mon = parse_time_digs(str + 4, 2); - day = parse_time_digs(str + 6, 2); - return parse_time_date_mkcal(year, mon, day); - - default: - return -1; - } -} - - - -int parse_time_time(const char* str, const char* end) -{ - const char* pos; - double d = 0; - char* endp; - int h = 0, m = 0, s = 0, ret; - - pos = strchr(str, '.'); - if(pos) { - errno = 0; - endp = 0; - d = strtod(pos, &endp); - if(errno || !endp) return -1; - switch(*endp) { - case 'Z': - case '+': - case '-': - case 0: - break; - - default: - return -1; - } - } else { - pos = end; - } - - /* Valid formats, excluding fraction, are: - * - * hh (len 2) - * hhmm (len 4) - * hh:mm (len 5) - * hhmmss (len 6) - * hh:mm:ss (len 8) - */ - switch(pos - str) { - case 2: - h = parse_time_digs(str, 2); - ret = ((h + d) * 3600 + 0.5); - break; - - case 4: - h = parse_time_digs(str, 2); - m = parse_time_digs(str + 2, 2); - ret = h * 3600 + ((m + d) * 60 + 0.5); - break; - - case 5: - h = parse_time_digs(str, 2); - m = parse_time_digs(str + 3, 2); - ret = h * 3600 + ((m + d) * 60 + 0.5); - break; - - case 6: - h = parse_time_digs(str, 2); - m = parse_time_digs(str + 2, 2); - s = parse_time_digs(str + 4, 2); - ret = h * 3600 + m * 60 + s + d + 0.5; - break; - - case 8: - h = parse_time_digs(str, 2); - m = parse_time_digs(str + 3, 2); - s = parse_time_digs(str + 6, 2); - ret = h * 3600 + m * 60 + s + d + 0.5; - break; - - default: - return -1; - } - - // special cases - if(h == 24 && m == 0 && s == 0) return ret; // midnight at end of day - if(h == 23 && m == 59 && s == 60) return ret; // leap second - - if(h < 0 || h > 23) return -1; - if(m < 0 || m > 59) return -1; - if(s < 0 || s > 59) return -1; - - return ret; -} - - - /* parse_time() * - * Parses an ISO-8601 date/time. We support any of the ISO-8601 formats. + * Parses an ISO-8601 date/time. We support any of the ISO-8601 formats. Uses libiso8601. On error, + * returns (time_t)-1. */ time_t parse_time(const char* str) { - const char* p, * tz; + struct iso8601_date iso; time_t t; - int s; - - // parse the date portion - p = strchr(str, 'T'); - t = p ? parse_time_date(str, p) : parse_time_date(str, str + strlen(str)); - if(t == (time_t)-1) return -1; - - // parse the time portion - if(p) { - ++p; - tz = strchr(p, 'Z'); - if(tz) { - if(tz[1]) return -1; - } else { - tz = strchr(p, '+'); - if(!tz) tz = strchr(p, '-'); - if(!tz) tz = p + strlen(p); - } - s = parse_time_time(p, tz); - if(s == -1) return -1; - t += s; - - p = tz + 1; - switch(*tz) { - case '+': - s = parse_time_time(p, p + strlen(p)); - if(s == -1) return -1; - t -= s; - break; - - case '-': - s = parse_time_time(p, p + strlen(p)); - if(s == -1) return -1; - t += s; - break; - } - } + if(iso8601_parse(str, &iso, 0, 0)) return (time_t)-1; + iso8601_to_time_t(&t, &iso); return t; } diff --git a/version b/version index 161e213..cf11b33 100644 --- a/version +++ b/version @@ -11,8 +11,8 @@ # expected to be in 'major.minor.micro' format. It can optionally be # suffixed with a string. VERMAJOR=1 -VERMINOR=0 -VERMICRO=1 +VERMINOR=1 +VERMICRO=0 VEREXTRA="" # kate: replace-trailing-space-save true; space-indent true; tab-width 4;