Git 2.9.4
[gitweb.git] / date.c
diff --git a/date.c b/date.c
index 8f9156909b8d9d2cad6425aa44deebdcd01b2168..a996331f5b33703c9f70844c6b49453ec39d16a7 100644 (file)
--- a/date.c
+++ b/date.c
@@ -74,6 +74,8 @@ static int local_tzoffset(unsigned long time)
        localtime_r(&t, &tm);
        t_local = tm_to_time_t(&tm);
 
+       if (t_local == -1)
+               return 0; /* error; just use +0000 */
        if (t_local < t) {
                eastwest = -1;
                offset = t - t_local;
@@ -166,6 +168,7 @@ struct date_mode *date_mode_from_type(enum date_mode_type type)
        if (type == DATE_STRFTIME)
                die("BUG: cannot create anonymous strftime date_mode struct");
        mode.type = type;
+       mode.local = 0;
        return &mode;
 }
 
@@ -174,6 +177,15 @@ const char *show_date(unsigned long time, int tz, const struct date_mode *mode)
        struct tm *tm;
        static struct strbuf timebuf = STRBUF_INIT;
 
+       if (mode->type == DATE_UNIX) {
+               strbuf_reset(&timebuf);
+               strbuf_addf(&timebuf, "%lu", time);
+               return timebuf.buf;
+       }
+
+       if (mode->local)
+               tz = local_tzoffset(time);
+
        if (mode->type == DATE_RAW) {
                strbuf_reset(&timebuf);
                strbuf_addf(&timebuf, "%lu %+05d", time, tz);
@@ -189,9 +201,6 @@ const char *show_date(unsigned long time, int tz, const struct date_mode *mode)
                return timebuf.buf;
        }
 
-       if (mode->type == DATE_LOCAL)
-               tz = local_tzoffset(time);
-
        tm = time_to_tm(time, tz);
        if (!tm) {
                tm = time_to_tm(0, 0);
@@ -232,7 +241,7 @@ const char *show_date(unsigned long time, int tz, const struct date_mode *mode)
                                tm->tm_mday,
                                tm->tm_hour, tm->tm_min, tm->tm_sec,
                                tm->tm_year + 1900,
-                               (mode->type == DATE_LOCAL) ? 0 : ' ',
+                               mode->local ? 0 : ' ',
                                tz);
        return timebuf.buf;
 }
@@ -770,31 +779,52 @@ int parse_date(const char *date, struct strbuf *result)
        return 0;
 }
 
+static enum date_mode_type parse_date_type(const char *format, const char **end)
+{
+       if (skip_prefix(format, "relative", end))
+               return DATE_RELATIVE;
+       if (skip_prefix(format, "iso8601-strict", end) ||
+           skip_prefix(format, "iso-strict", end))
+               return DATE_ISO8601_STRICT;
+       if (skip_prefix(format, "iso8601", end) ||
+           skip_prefix(format, "iso", end))
+               return DATE_ISO8601;
+       if (skip_prefix(format, "rfc2822", end) ||
+           skip_prefix(format, "rfc", end))
+               return DATE_RFC2822;
+       if (skip_prefix(format, "short", end))
+               return DATE_SHORT;
+       if (skip_prefix(format, "default", end))
+               return DATE_NORMAL;
+       if (skip_prefix(format, "raw", end))
+               return DATE_RAW;
+       if (skip_prefix(format, "unix", end))
+               return DATE_UNIX;
+       if (skip_prefix(format, "format", end))
+               return DATE_STRFTIME;
+
+       die("unknown date format %s", format);
+}
+
 void parse_date_format(const char *format, struct date_mode *mode)
 {
-       if (!strcmp(format, "relative"))
-               mode->type = DATE_RELATIVE;
-       else if (!strcmp(format, "iso8601") ||
-                !strcmp(format, "iso"))
-               mode->type = DATE_ISO8601;
-       else if (!strcmp(format, "iso8601-strict") ||
-                !strcmp(format, "iso-strict"))
-               mode->type = DATE_ISO8601_STRICT;
-       else if (!strcmp(format, "rfc2822") ||
-                !strcmp(format, "rfc"))
-               mode->type = DATE_RFC2822;
-       else if (!strcmp(format, "short"))
-               mode->type = DATE_SHORT;
-       else if (!strcmp(format, "local"))
-               mode->type = DATE_LOCAL;
-       else if (!strcmp(format, "default"))
-               mode->type = DATE_NORMAL;
-       else if (!strcmp(format, "raw"))
-               mode->type = DATE_RAW;
-       else if (skip_prefix(format, "format:", &format)) {
-               mode->type = DATE_STRFTIME;
-               mode->strftime_fmt = xstrdup(format);
-       } else
+       const char *p;
+
+       /* historical alias */
+       if (!strcmp(format, "local"))
+               format = "default-local";
+
+       mode->type = parse_date_type(format, &p);
+       mode->local = 0;
+
+       if (skip_prefix(p, "-local", &p))
+               mode->local = 1;
+
+       if (mode->type == DATE_STRFTIME) {
+               if (!skip_prefix(p, ":", &p))
+                       die("date format missing colon separator: %s", format);
+               mode->strftime_fmt = xstrdup(p);
+       } else if (*p)
                die("unknown date format %s", format);
 }