diff options
Diffstat (limited to 'date.c')
-rw-r--r-- | date.c | 96 |
1 files changed, 70 insertions, 26 deletions
@@ -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,37 @@ 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->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); return timebuf.buf; } - if (mode == DATE_RELATIVE) { + if (mode->type == DATE_RELATIVE) { struct timeval now; strbuf_reset(&timebuf); @@ -180,9 +201,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 +208,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 +227,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 +241,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 +779,52 @@ 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, "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) +{ + 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); } |