X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=date.c;h=950b88fdcf74f550a582684f1702ffb58c62c7f9;hb=297f6a535cb46d246d47a9ff2473cef4ee1ada27;hp=8f7050027053a4e2390097e341327b117404c26a;hpb=ada59fcd3230e661bc1110702a2fb4ef76371bc1;p=git.git diff --git a/date.c b/date.c index 8f7050027..950b88fdc 100644 --- a/date.c +++ b/date.c @@ -6,7 +6,10 @@ #include "cache.h" -static time_t my_mktime(struct tm *tm) +/* + * This is like mktime, but without normalization of tm_wday and tm_yday. + */ +time_t tm_to_time_t(const struct tm *tm) { static const int mdays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 @@ -67,7 +70,7 @@ static int local_tzoffset(unsigned long time) t = time; localtime_r(&t, &tm); - t_local = my_mktime(&tm); + t_local = tm_to_time_t(&tm); if (t_local < t) { eastwest = -1; @@ -213,9 +216,9 @@ static const struct { { "EAST", +10, 0, }, /* Eastern Australian Standard */ { "EADT", +10, 1, }, /* Eastern Australian Daylight */ { "GST", +10, 0, }, /* Guam Standard, USSR Zone 9 */ - { "NZT", +11, 0, }, /* New Zealand */ - { "NZST", +11, 0, }, /* New Zealand Standard */ - { "NZDT", +11, 1, }, /* New Zealand Daylight */ + { "NZT", +12, 0, }, /* New Zealand */ + { "NZST", +12, 0, }, /* New Zealand Standard */ + { "NZDT", +12, 1, }, /* New Zealand Daylight */ { "IDLE", +12, 0, }, /* International Date Line East */ }; @@ -322,7 +325,7 @@ static int is_date(int year, int month, int day, struct tm *now_tm, time_t now, if (!now_tm) return 1; - specified = my_mktime(r); + specified = tm_to_time_t(r); /* Be it commit time or author time, it does not make * sense to specify timestamp way into the future. Make @@ -399,6 +402,15 @@ static int match_multi_number(unsigned long num, char c, const char *date, char return end - date; } +/* Have we filled in any part of the time/date yet? */ +static inline int nodate(struct tm *tm) +{ + return tm->tm_year < 0 && + tm->tm_mon < 0 && + tm->tm_mday < 0 && + !(tm->tm_hour | tm->tm_min | tm->tm_sec); +} + /* * We've seen a digit. Time? Year? Date? */ @@ -415,7 +427,7 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt * more than 8 digits. This is because we don't want to rule out * numbers like 20070606 as a YYYYMMDD date. */ - if (num >= 100000000) { + if (num >= 100000000 && nodate(tm)) { time_t time = num; if (gmtime_r(&time, tm)) { *tm_gmt = 1; @@ -459,6 +471,13 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt return n; } + /* + * Ignore lots of numerals. We took care of 4-digit years above. + * Days or months must be one or two digits. + */ + if (n > 2) + return n; + /* * NOTE! We will give precedence to day-of-month over month or * year numbers in the 1-12 range. So 05 is always "mday 5", @@ -485,10 +504,6 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt if (num > 0 && num < 32) { tm->tm_mday = num; - } else if (num > 1900) { - tm->tm_year = num - 1900; - } else if (num > 70) { - tm->tm_year = num; } else if (num > 0 && num < 13) { tm->tm_mon = num-1; } @@ -572,7 +587,7 @@ int parse_date(const char *date, char *result, int maxlen) } /* mktime uses local timezone */ - then = my_mktime(&tm); + then = tm_to_time_t(&tm); if (offset == -1) offset = (then - mktime(&tm)) / 60; @@ -611,7 +626,7 @@ void datestamp(char *buf, int bufsize) time(&now); - offset = my_mktime(localtime(&now)) - now; + offset = tm_to_time_t(localtime(&now)) - now; offset /= 60; date_string(now, offset, buf, bufsize); @@ -682,10 +697,8 @@ static void date_am(struct tm *tm, int *num) static void date_never(struct tm *tm, int *num) { - tm->tm_mon = tm->tm_wday = tm->tm_yday - = tm->tm_hour = tm->tm_min = tm->tm_sec = 0; - tm->tm_year = 70; - tm->tm_mday = 1; + time_t n = 0; + localtime_r(&n, tm); } static const struct special { @@ -822,7 +835,9 @@ static const char *approxidate_digit(const char *date, struct tm *tm, int *num) } } - *num = number; + /* Accept zero-padding only for small numbers ("Dec 02", never "Dec 0002") */ + if (date[0] != '0' || end - date <= 2) + *num = number; return end; }