diff options
-rw-r--r-- | builtin-cat-file.c | 2 | ||||
-rw-r--r-- | cache.h | 2 | ||||
-rw-r--r-- | commit.c | 4 | ||||
-rw-r--r-- | date.c | 63 |
4 files changed, 59 insertions, 12 deletions
diff --git a/builtin-cat-file.c b/builtin-cat-file.c index 7a6fa56e93..6c16bfa1ae 100644 --- a/builtin-cat-file.c +++ b/builtin-cat-file.c @@ -54,7 +54,7 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long write_or_die(1, tagger, sp - tagger); date = strtoul(sp, &ep, 10); tz = strtol(ep, NULL, 10); - sp = show_date(date, tz); + sp = show_date(date, tz, 0); write_or_die(1, sp, strlen(sp)); xwrite(1, "\n", 1); break; @@ -286,7 +286,7 @@ extern void *read_object_with_reference(const unsigned char *sha1, unsigned long *size, unsigned char *sha1_ret); -const char *show_date(unsigned long time, int timezone); +const char *show_date(unsigned long time, int timezone, int relative); const char *show_rfc2822_date(unsigned long time, int timezone); int parse_date(const char *date, char *buf, int bufsize); void datestamp(char *buf, int bufsize); @@ -507,14 +507,14 @@ static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, const c } switch (fmt) { case CMIT_FMT_MEDIUM: - ret += sprintf(buf + ret, "Date: %s\n", show_date(time, tz)); + ret += sprintf(buf + ret, "Date: %s\n", show_date(time, tz, 0)); break; case CMIT_FMT_EMAIL: ret += sprintf(buf + ret, "Date: %s\n", show_rfc2822_date(time, tz)); break; case CMIT_FMT_FULLER: - ret += sprintf(buf + ret, "%sDate: %s\n", what, show_date(time, tz)); + ret += sprintf(buf + ret, "%sDate: %s\n", what, show_date(time, tz, 0)); break; default: /* notin' */ @@ -37,6 +37,16 @@ static const char *weekday_names[] = { "Sundays", "Mondays", "Tuesdays", "Wednesdays", "Thursdays", "Fridays", "Saturdays" }; +static time_t gm_time_t(unsigned long time, int tz) +{ + int minutes; + + minutes = tz < 0 ? -tz : tz; + minutes = (minutes / 100)*60 + (minutes % 100); + minutes = tz < 0 ? -minutes : minutes; + return time + minutes * 60; +} + /* * The "tz" thing is passed in as this strange "decimal parse of tz" * thing, which means that tz -0100 is passed in as the integer -100, @@ -44,21 +54,58 @@ static const char *weekday_names[] = { */ static struct tm *time_to_tm(unsigned long time, int tz) { - time_t t; - int minutes; - - minutes = tz < 0 ? -tz : tz; - minutes = (minutes / 100)*60 + (minutes % 100); - minutes = tz < 0 ? -minutes : minutes; - t = time + minutes * 60; + time_t t = gm_time_t(time, tz); return gmtime(&t); } -const char *show_date(unsigned long time, int tz) +const char *show_date(unsigned long time, int tz, int relative) { struct tm *tm; static char timebuf[200]; + if (relative) { + unsigned long diff; + time_t t = gm_time_t(time, tz); + struct timeval now; + gettimeofday(&now, NULL); + if (now.tv_sec < t) + return "in the future"; + diff = now.tv_sec - t; + if (diff < 90) { + snprintf(timebuf, sizeof(timebuf), "%lu seconds ago", diff); + return timebuf; + } + /* Turn it into minutes */ + diff = (diff + 30) / 60; + if (diff < 90) { + snprintf(timebuf, sizeof(timebuf), "%lu minutes ago", diff); + return timebuf; + } + /* Turn it into hours */ + diff = (diff + 30) / 60; + if (diff < 36) { + snprintf(timebuf, sizeof(timebuf), "%lu hours ago", diff); + return timebuf; + } + /* We deal with number of days from here on */ + diff = (diff + 12) / 24; + if (diff < 14) { + snprintf(timebuf, sizeof(timebuf), "%lu days ago", diff); + return timebuf; + } + /* Say weeks for the past 10 weeks or so */ + if (diff < 70) { + snprintf(timebuf, sizeof(timebuf), "%lu weeks ago", (diff + 3) / 7); + return timebuf; + } + /* Say months for the past 12 months or so */ + if (diff < 360) { + snprintf(timebuf, sizeof(timebuf), "%lu months ago", (diff + 15) / 30); + return timebuf; + } + /* Else fall back on absolute format.. */ + } + tm = time_to_tm(time, tz); if (!tm) return NULL; |