summaryrefslogtreecommitdiff
path: root/date.c
diff options
context:
space:
mode:
Diffstat (limited to 'date.c')
-rw-r--r--date.c88
1 files changed, 62 insertions, 26 deletions
diff --git a/date.c b/date.c
index 733d1b29b1..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;
@@ -160,18 +162,31 @@ void show_date_relative(unsigned long time, int tz,
(diff + 183) / 365);
}
-const char *show_date(unsigned long time, int tz, enum date_mode mode)
+struct date_mode *date_mode_from_type(enum date_mode_type type)
+{
+ static struct date_mode mode;
+ if (type == DATE_STRFTIME)
+ die("BUG: cannot create anonymous strftime date_mode struct");
+ mode.type = type;
+ mode.local = 0;
+ return &mode;
+}
+
+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 == DATE_RAW) {
+ if (mode->local)
+ tz = local_tzoffset(time);
+
+ if (mode->type == DATE_RAW) {
strbuf_reset(&timebuf);
strbuf_addf(&timebuf, "%lu %+05d", time, tz);
return timebuf.buf;
}
- if (mode == DATE_RELATIVE) {
+ if (mode->type == DATE_RELATIVE) {
struct timeval now;
strbuf_reset(&timebuf);
@@ -180,9 +195,6 @@ const char *show_date(unsigned long time, int tz, enum date_mode mode)
return timebuf.buf;
}
- if (mode == DATE_LOCAL)
- tz = local_tzoffset(time);
-
tm = time_to_tm(time, tz);
if (!tm) {
tm = time_to_tm(0, 0);
@@ -190,17 +202,17 @@ const char *show_date(unsigned long time, int tz, enum date_mode mode)
}
strbuf_reset(&timebuf);
- if (mode == DATE_SHORT)
+ if (mode->type == DATE_SHORT)
strbuf_addf(&timebuf, "%04d-%02d-%02d", tm->tm_year + 1900,
tm->tm_mon + 1, tm->tm_mday);
- else if (mode == DATE_ISO8601)
+ else if (mode->type == DATE_ISO8601)
strbuf_addf(&timebuf, "%04d-%02d-%02d %02d:%02d:%02d %+05d",
tm->tm_year + 1900,
tm->tm_mon + 1,
tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
tz);
- else if (mode == DATE_ISO8601_STRICT) {
+ else if (mode->type == DATE_ISO8601_STRICT) {
char sign = (tz >= 0) ? '+' : '-';
tz = abs(tz);
strbuf_addf(&timebuf, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
@@ -209,11 +221,13 @@ 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,
sign, tz / 100, tz % 100);
- } else if (mode == DATE_RFC2822)
+ } else if (mode->type == 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,
tm->tm_hour, tm->tm_min, tm->tm_sec, tz);
+ else if (mode->type == DATE_STRFTIME)
+ strbuf_addftime(&timebuf, mode->strftime_fmt, tm);
else
strbuf_addf(&timebuf, "%.3s %.3s %d %02d:%02d:%02d %d%c%+05d",
weekday_names[tm->tm_wday],
@@ -221,7 +235,7 @@ 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,
tm->tm_year + 1900,
- (mode == DATE_LOCAL) ? 0 : ' ',
+ mode->local ? 0 : ' ',
tz);
return timebuf.buf;
}
@@ -759,28 +773,50 @@ int parse_date(const char *date, struct strbuf *result)
return 0;
}
-enum date_mode parse_date_format(const char *format)
+static enum date_mode_type parse_date_type(const char *format, const char **end)
{
- if (!strcmp(format, "relative"))
+ if (skip_prefix(format, "relative", end))
return DATE_RELATIVE;
- else if (!strcmp(format, "iso8601") ||
- !strcmp(format, "iso"))
- return DATE_ISO8601;
- else if (!strcmp(format, "iso8601-strict") ||
- !strcmp(format, "iso-strict"))
+ if (skip_prefix(format, "iso8601-strict", end) ||
+ skip_prefix(format, "iso-strict", end))
return DATE_ISO8601_STRICT;
- else if (!strcmp(format, "rfc2822") ||
- !strcmp(format, "rfc"))
+ 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;
- else if (!strcmp(format, "short"))
+ if (skip_prefix(format, "short", end))
return DATE_SHORT;
- else if (!strcmp(format, "local"))
- return DATE_LOCAL;
- else if (!strcmp(format, "default"))
+ if (skip_prefix(format, "default", end))
return DATE_NORMAL;
- else if (!strcmp(format, "raw"))
+ if (skip_prefix(format, "raw", end))
return DATE_RAW;
- else
+ 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)
+{
+ 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);
}