diff.c: --ws-error-highlight=<kind> option
[gitweb.git] / date.c
diff --git a/date.c b/date.c
index 2c33468dfbf445017a1925065004646942a3cb75..3eba2dfe8841cee28850e2f1f4177e1e32f1c8a8 100644 (file)
--- a/date.c
+++ b/date.c
@@ -200,7 +200,16 @@ const char *show_date(unsigned long time, int tz, enum date_mode mode)
                                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,
@@ -396,9 +405,9 @@ static int is_date(int year, int month, int day, struct tm *now_tm, time_t now,
        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;
@@ -424,17 +433,18 @@ static int match_multi_number(unsigned long num, char c, const char *date, char
        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]
@@ -504,7 +514,7 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt
        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;
                }
@@ -752,6 +762,9 @@ enum date_mode parse_date_format(const char *format)
        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;
@@ -1001,7 +1014,8 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
        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);
@@ -1012,7 +1026,8 @@ static const char *approxidate_digit(const char *date, struct tm *tm, int *num)
        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;
                }
@@ -1075,7 +1090,7 @@ static unsigned long approxidate_str(const char *date,
                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;
                }