From: Junio C Hamano Date: Mon, 11 May 2015 21:33:58 +0000 (-0700) Subject: Merge branch 'jc/epochtime-wo-tz' into maint-2.3 X-Git-Tag: v2.3.8~4 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/13ec221d8cb054051cd9d4da236b4f7dc6facbfb?hp=-c Merge branch 'jc/epochtime-wo-tz' into maint-2.3 "git commit --date=now" or anything that relies on approxidate lost the daylight-saving-time offset. * jc/epochtime-wo-tz: parse_date_basic(): let the system handle DST conversion parse_date_basic(): return early when given a bogus timestamp --- 13ec221d8cb054051cd9d4da236b4f7dc6facbfb diff --combined date.c index 3eba2dfe88,52a99448d2..733d1b29b1 --- a/date.c +++ b/date.c @@@ -200,16 -200,7 +200,16 @@@ const char *show_date(unsigned long tim tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, tz); - else if (mode == DATE_RFC2822) + else if (mode == DATE_ISO8601_STRICT) { + char sign = (tz >= 0) ? '+' : '-'; + tz = abs(tz); + strbuf_addf(&timebuf, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d", + tm->tm_year + 1900, + tm->tm_mon + 1, + tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec, + sign, tz / 100, tz % 100); + } else if (mode == DATE_RFC2822) strbuf_addf(&timebuf, "%.3s, %d %.3s %d %02d:%02d:%02d %+05d", weekday_names[tm->tm_wday], tm->tm_mday, month_names[tm->tm_mon], tm->tm_year + 1900, @@@ -405,9 -396,9 +405,9 @@@ static int is_date(int year, int month return 0; } -static int match_multi_number(unsigned long num, char c, const char *date, char *end, struct tm *tm) +static int match_multi_number(unsigned long num, char c, const char *date, + char *end, struct tm *tm, time_t now) { - time_t now; struct tm now_tm; struct tm *refuse_future; long num2, num3; @@@ -433,18 -424,17 +433,18 @@@ case '-': case '/': case '.': - now = time(NULL); + if (!now) + now = time(NULL); refuse_future = NULL; if (gmtime_r(&now, &now_tm)) refuse_future = &now_tm; if (num > 70) { /* yyyy-mm-dd? */ - if (is_date(num, num2, num3, refuse_future, now, tm)) + if (is_date(num, num2, num3, NULL, now, tm)) break; /* yyyy-dd-mm? */ - if (is_date(num, num3, num2, refuse_future, now, tm)) + if (is_date(num, num3, num2, NULL, now, tm)) break; } /* Our eastern European friends say dd.mm.yy[yy] @@@ -514,7 -504,7 +514,7 @@@ static int match_digit(const char *date case '/': case '-': if (isdigit(end[1])) { - int match = match_multi_number(num, *end, date, end, tm); + int match = match_multi_number(num, *end, date, end, tm, 0); if (match) return match; } @@@ -615,7 -605,7 +615,7 @@@ static int match_tz(const char *date, i return end - date; } -static int date_string(unsigned long date, int offset, char *buf, int len) +static void date_string(unsigned long date, int offset, struct strbuf *buf) { int sign = '+'; @@@ -623,7 -613,7 +623,7 @@@ offset = -offset; sign = '-'; } - return snprintf(buf, len, "%lu %c%02d%02d", date, sign, offset / 60, offset % 60); + strbuf_addf(buf, "%lu %c%02d%02d", date, sign, offset / 60, offset % 60); } /* @@@ -704,10 -694,17 +704,17 @@@ int parse_date_basic(const char *date, date += match; } - /* mktime uses local timezone */ + /* do not use mktime(), which uses local timezone, here */ *timestamp = tm_to_time_t(&tm); + if (*timestamp == -1) + return -1; + if (*offset == -1) { - time_t temp_time = mktime(&tm); + time_t temp_time; + + /* gmtime_r() in match_digit() may have clobbered it */ + tm.tm_isdst = -1; + temp_time = mktime(&tm); if ((time_t)*timestamp > temp_time) { *offset = ((time_t)*timestamp - temp_time) / 60; } else { @@@ -715,9 -712,6 +722,6 @@@ } } - if (*timestamp == -1) - return -1; - if (!tm_gmt) *timestamp -= *offset * 60; return 0; /* success */ @@@ -745,14 -739,13 +749,14 @@@ int parse_expiry_date(const char *date return errors; } -int parse_date(const char *date, char *result, int maxlen) +int parse_date(const char *date, struct strbuf *result) { unsigned long timestamp; int offset; if (parse_date_basic(date, ×tamp, &offset)) return -1; - return date_string(timestamp, offset, result, maxlen); + date_string(timestamp, offset, result); + return 0; } enum date_mode parse_date_format(const char *format) @@@ -762,9 -755,6 +766,9 @@@ else if (!strcmp(format, "iso8601") || !strcmp(format, "iso")) return DATE_ISO8601; + else if (!strcmp(format, "iso8601-strict") || + !strcmp(format, "iso-strict")) + return DATE_ISO8601_STRICT; else if (!strcmp(format, "rfc2822") || !strcmp(format, "rfc")) return DATE_RFC2822; @@@ -780,7 -770,7 +784,7 @@@ die("unknown date format %s", format); } -void datestamp(char *buf, int bufsize) +void datestamp(struct strbuf *out) { time_t now; int offset; @@@ -790,7 -780,7 +794,7 @@@ offset = tm_to_time_t(localtime(&now)) - now; offset /= 60; - date_string(now, offset, buf, bufsize); + date_string(now, offset, out); } /* @@@ -1014,8 -1004,7 +1018,8 @@@ static const char *approxidate_alpha(co return end; } -static const char *approxidate_digit(const char *date, struct tm *tm, int *num) +static const char *approxidate_digit(const char *date, struct tm *tm, int *num, + time_t now) { char *end; unsigned long number = strtoul(date, &end, 10); @@@ -1026,8 -1015,7 +1030,8 @@@ case '/': case '-': if (isdigit(end[1])) { - int match = match_multi_number(number, *end, date, end, tm); + int match = match_multi_number(number, *end, date, end, + tm, now); if (match) return date + match; } @@@ -1090,7 -1078,7 +1094,7 @@@ static unsigned long approxidate_str(co date++; if (isdigit(c)) { pending_number(&tm, &number); - date = approxidate_digit(date-1, &tm, &number); + date = approxidate_digit(date-1, &tm, &number, time_sec); touched = 1; continue; }