summaryrefslogtreecommitdiff
path: root/date.c
diff options
context:
space:
mode:
Diffstat (limited to 'date.c')
-rw-r--r--date.c76
1 files changed, 49 insertions, 27 deletions
diff --git a/date.c b/date.c
index 8f9156909b..4c7aa9ba85 100644
--- 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,9 @@ 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->local)
+ tz = local_tzoffset(time);
+
if (mode->type == DATE_RAW) {
strbuf_reset(&timebuf);
strbuf_addf(&timebuf, "%lu %+05d", time, tz);
@@ -189,9 +195,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 +235,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 +773,50 @@ 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, "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);
}