Linus Torvalds wrote: > > [...] I just rewrote it to give "almost correct > results" for "pretty much any crap you throw at it". And I had the impression the strict checks in the original version were intentionally ;-) > I'll probably tweak it a bit more (make "no timezone means local > timezone", for example, rather than UTC like it is now). Here's my try on that. But whether it works everywhere ... Btw, your %+03d%02d printf gave wrong results for i.e. -0130 (-01-30). --- k/date.c (mode:100644) +++ l/date.c (mode:100644) @@ -10,7 +10,9 @@ #include <ctype.h> #include <time.h> -static time_t my_mktime(struct tm *tm) +#define NO_TZ 11111 + +static time_t utc_mktime(struct tm *tm) { static const int mdays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 @@ -23,12 +25,19 @@ static time_t my_mktime(struct tm *tm) return -1; if (month < 0 || month > 11) /* array bounds */ return -1; + if (day < 1 || day > 31) + return -1; if (month < 2 || (year + 2) % 4) day--; return (year * 365 + (year + 1) / 4 + mdays[month] + day) * 24*60*60UL + tm->tm_hour * 60*60 + tm->tm_min * 60 + tm->tm_sec; } +static int local_offset(time_t *when) +{ + return (utc_mktime(localtime(when)) - *when) / 60; +} + static const char *month_names[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" @@ -138,7 +147,8 @@ static int match_alpha(const char *date, for (i = 0; i < NR_TZ; i++) { int match = match_string(date, timezone_names[i].name); if (match >= 3) { - *offset = 60*timezone_names[i].offset; + if (*offset == NO_TZ) + *offset = 60*timezone_names[i].offset; return match; } } @@ -245,7 +255,7 @@ void parse_date(char *date, char *result tm.tm_year = -1; tm.tm_mon = -1; tm.tm_mday = -1; - offset = 0; + offset = NO_TZ; for (;;) { int match = 0; @@ -270,13 +280,20 @@ void parse_date(char *date, char *result date += match; } - then = my_mktime(&tm); /* mktime uses local timezone */ - if (then == -1) - return; - - then -= offset * 60; + if (offset == NO_TZ) { + tm.tm_isdst = -1; + then = mktime(&tm); + if (then == -1) + return; + offset = local_offset(&then); + } else { + then = utc_mktime(&tm); + if (then == -1) + return; + then -= offset * 60; + } - snprintf(result, maxlen, "%lu %+03d%02d", then, offset/60, offset % 60); + snprintf(result, maxlen, "%lu %+05d", then, offset/60*100 + offset%60); } void datestamp(char *buf, int bufsize) @@ -285,9 +302,7 @@ void datestamp(char *buf, int bufsize) int offset; time(&now); - - offset = my_mktime(localtime(&now)) - now; - offset /= 60; + offset = local_offset(&now); snprintf(buf, bufsize, "%lu %+05d", now, offset/60*100 + offset%60); } Ciao, ET. - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.htmlReceived on Sun May 01 08:56:16 2005
This archive was generated by hypermail 2.1.8 : 2005-05-01 08:56:16 EST