Separate the logic to decide which presentation (e.g. "N months") to use based on the length of the time from the present and actual presentation (i.e. "strbuf_addf()"). This is not strictly needed but will make the next step easier to read. The format strings lost N_() markings along the way; help from the i18n folks to come up with the best and sane way to mark them up is very much appreciated. Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx> --- date.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 127 insertions(+), 43 deletions(-) diff --git a/date.c b/date.c index 57331ed..b6ff04e 100644 --- a/date.c +++ b/date.c @@ -86,78 +86,162 @@ static int local_tzoffset(unsigned long time) return offset * eastwest; } -void show_date_relative(unsigned long time, int tz, - const struct timeval *now, - struct strbuf *timebuf) +enum relative_style { + rd_seconds = 0, rd_minutes, rd_hours, rd_days, rd_weeks, rd_months, rd_years +}; + +struct relative_date { + int seconds; + int minutes; + int hours; + int days; + int weeks; + int months; + int years; +}; + +static enum relative_style format_relative_date(unsigned long diff, + struct relative_date *rd) { - unsigned long diff; - if (now->tv_sec < time) { - strbuf_addstr(timebuf, _("in the future")); - return; - } - diff = now->tv_sec - time; + memset(rd, 0, sizeof(*rd)); if (diff < 90) { - strbuf_addf(timebuf, - Q_("%lu second ago", "%lu seconds ago", diff), diff); - return; + rd->seconds = diff; + return rd_seconds; } /* Turn it into minutes */ diff = (diff + 30) / 60; if (diff < 90) { - strbuf_addf(timebuf, - Q_("%lu minute ago", "%lu minutes ago", diff), diff); - return; + rd->minutes = diff; + return rd_minutes; } /* Turn it into hours */ diff = (diff + 30) / 60; if (diff < 36) { - strbuf_addf(timebuf, - Q_("%lu hour ago", "%lu hours ago", diff), diff); - return; + rd->hours = diff; + return rd_hours; } /* We deal with number of days from here on */ diff = (diff + 12) / 24; if (diff < 14) { - strbuf_addf(timebuf, - Q_("%lu day ago", "%lu days ago", diff), diff); - return; + rd->days = diff; + return rd_days; } /* Say weeks for the past 10 weeks or so */ if (diff < 70) { - strbuf_addf(timebuf, - Q_("%lu week ago", "%lu weeks ago", (diff + 3) / 7), - (diff + 3) / 7); - return; + rd->weeks = (diff + 3) / 7; + return rd_weeks; } /* Say months for the past 12 months or so */ if (diff < 365) { - strbuf_addf(timebuf, - Q_("%lu month ago", "%lu months ago", (diff + 15) / 30), - (diff + 15) / 30); - return; + rd->months = (diff + 15) / 30; + return rd_months; } /* Give years and months for 5 years or so */ if (diff < 1825) { unsigned long totalmonths = (diff * 12 * 2 + 365) / (365 * 2); - unsigned long years = totalmonths / 12; - unsigned long months = totalmonths % 12; - if (months) { + rd->years = totalmonths / 12; + rd->months = totalmonths % 12; + return rd_years; + } + /* Otherwise, just years. Centuries is probably overkill. */ + rd->years = (diff + 183) / 365; + return rd_years; +} + +void show_date_relative(unsigned long time, int tz, + const struct timeval *now, + struct strbuf *timebuf) +{ + unsigned long diff; + struct relative_date rd; + int pf = 0; /* past or future */ + + struct { + struct { const char *s, *p; } msg_seconds; + struct { const char *s, *p; } msg_minutes; + struct { const char *s, *p; } msg_hours; + struct { const char *s, *p; } msg_days; + struct { const char *s, *p; } msg_weeks; + struct { const char *s, *p; } msg_months; + struct { const char *s, *p; } msg_years_only; + struct { const char *s, *p; } msg_years_months; + struct { const char *s, *p; } msg_years; + } msg[1] = { + { + { "%lu second ago", "%lu seconds ago" }, + { "%lu minute ago", "%lu minutes ago" }, + { "%lu hour ago", "%lu hours ago" }, + { "%lu day ago", "%lu days ago" }, + { "%lu week ago", "%lu weeks ago" }, + { "%lu month ago", "%lu months ago" }, + { "%lu year", "%lu years" }, + { + /* TRANSLATORS: "%s" is "<n> years" */ + "%s, %lu month ago", + /* TRANSLATORS: "%s" is "<n> years" */ + "%s, %lu months ago" + }, + { "%lu year ago", "%lu years ago" }, + } + }; + + if (now->tv_sec < time) { + strbuf_addstr(timebuf, _("in the future")); + return; + } + diff = now->tv_sec - time; + + switch (format_relative_date(diff, &rd)) { + case rd_seconds: + strbuf_addf(timebuf, + Q_(msg[pf].msg_seconds.s, msg[pf].msg_seconds.p, + rd.seconds), rd.seconds); + break; + case rd_minutes: + strbuf_addf(timebuf, + Q_(msg[pf].msg_minutes.s, msg[pf].msg_minutes.p, + rd.minutes), rd.minutes); + break; + case rd_hours: + strbuf_addf(timebuf, + Q_(msg[pf].msg_hours.s, msg[pf].msg_hours.p, + rd.hours), rd.hours); + break; + case rd_days: + strbuf_addf(timebuf, + Q_(msg[pf].msg_days.s, msg[pf].msg_days.p, + rd.days), rd.days); + break; + case rd_weeks: + strbuf_addf(timebuf, + Q_(msg[pf].msg_weeks.s, msg[pf].msg_weeks.p, + rd.weeks), rd.weeks); + break; + case rd_months: + strbuf_addf(timebuf, + Q_(msg[pf].msg_months.s, msg[pf].msg_months.p, + rd.months), rd.months); + break; + + case rd_years: + if (rd.months) { struct strbuf sb = STRBUF_INIT; - strbuf_addf(&sb, Q_("%lu year", "%lu years", years), years); - /* TRANSLATORS: "%s" is "<n> years" */ + strbuf_addf(&sb, Q_(msg[pf].msg_years_only.s, + msg[pf].msg_years_only.p, + rd.years), rd.years); strbuf_addf(timebuf, - Q_("%s, %lu month ago", "%s, %lu months ago", months), - sb.buf, months); + Q_(msg[pf].msg_years_months.s, + msg[pf].msg_years_months.p, + rd.months), + sb.buf, rd.months); strbuf_release(&sb); - } else + } else { strbuf_addf(timebuf, - Q_("%lu year ago", "%lu years ago", years), years); - return; + Q_(msg[pf].msg_years.s, msg[pf].msg_years.p, + rd.years), rd.years); + } + break; } - /* Otherwise, just years. Centuries is probably overkill. */ - strbuf_addf(timebuf, - Q_("%lu year ago", "%lu years ago", (diff + 183) / 365), - (diff + 183) / 365); } const char *show_date(unsigned long time, int tz, enum date_mode mode) -- 1.7.12.rc3.69.gaf0166d -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html