>From b51bc56816490c71cd37f52be73a06cef6b9bf14 Mon Sep 17 00:00:00 2001 From: Alex Riesen <raa.lkml@xxxxxxxxx> Date: Fri, 28 Aug 2009 20:59:59 +0200 Subject: [PATCH] Add date formatting functions with current time explicitely formatted It should allow safe testing of this part of the code. --- Nicolas Pitre, Fri, Aug 28, 2009 19:28:34 +0200: > On Fri, 28 Aug 2009, Jeff King wrote: > > On Fri, Aug 28, 2009 at 09:58:27AM +0200, Alex Riesen wrote: > > > > > > I couldn't find any tests related to relative date processing, so it > > > > would be really nice to have some. But I'm not sure of the best way to > > > > do it without dealing with race conditions. Annoyingly, show_date calls > > > > gettimeofday at a pretty low level, so there isn't a way of > > > > instrumenting it short of LD_PRELOAD trickery (which is probably not > > > > very portable). > > > > > > Maybe better prepare the _test_ so that it uses current time and time > > > arithmetics then put yet another cludge in operational code? Especially > > > when we already have a greate number of GIT_ environment variables, > > > documented nowhere, with effects not immediately obvious: > > > > But that's the point: you can't do that without a race condition. Your > > test gets a sense of the current time, then runs git, which checks the > > current time again. How many seconds elapsed between the two checks? > > > > I guess it is good enough for testing large time spans, but I was hoping > > for a comprehensive time test. > > I agree with your concern. This is why I created the --index-version > switch to pack-objects. > This is what I mean with "supplying current time": cache.h | 2 + date.c | 130 ++++++++++++++++++++++++++++++++++---------------------------- 2 files changed, 73 insertions(+), 59 deletions(-) diff --git a/cache.h b/cache.h index dd7f71e..3fb0166 100644 --- a/cache.h +++ b/cache.h @@ -731,9 +731,11 @@ enum date_mode { }; const char *show_date(unsigned long time, int timezone, enum date_mode mode); +const char *show_date_relative(unsigned long time, int tz, const struct timeval *now); int parse_date(const char *date, char *buf, int bufsize); void datestamp(char *buf, int bufsize); unsigned long approxidate(const char *); +unsigned long approxidate_relative(const char *date, const struct timeval *now); enum date_mode parse_date_format(const char *format); #define IDENT_WARN_ON_NO_NAME 1 diff --git a/date.c b/date.c index 409a17d..08b4b49 100644 --- a/date.c +++ b/date.c @@ -84,6 +84,67 @@ static int local_tzoffset(unsigned long time) return offset * eastwest; } +const char *show_date_relative(unsigned long time, int tz, const struct timeval *now) +{ + static char timebuf[100 /* TODO: can be optimized */]; + unsigned long diff; + if (now->tv_sec < time) + return "in the future"; + diff = now->tv_sec - time; + 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; + } + /* Give years and months for 5 years or so */ + if (diff < 1825) { + unsigned long years = (diff + 183) / 365; + unsigned long months = (diff % 365 + 15) / 30; + int n; + n = snprintf(timebuf, sizeof(timebuf), "%lu year%s", + years, (years > 1 ? "s" : "")); + if (months) + snprintf(timebuf + n, sizeof(timebuf) - n, + ", %lu month%s ago", + months, (months > 1 ? "s" : "")); + else + snprintf(timebuf + n, sizeof(timebuf) - n, + " ago"); + return timebuf; + } + /* Otherwise, just years. Centuries is probably overkill. */ + snprintf(timebuf, sizeof(timebuf), "%lu years ago", (diff + 183) / 365); + return timebuf; + +} + const char *show_date(unsigned long time, int tz, enum date_mode mode) { struct tm *tm; @@ -95,63 +156,9 @@ const char *show_date(unsigned long time, int tz, enum date_mode mode) } if (mode == DATE_RELATIVE) { - unsigned long diff; struct timeval now; gettimeofday(&now, NULL); - if (now.tv_sec < time) - return "in the future"; - diff = now.tv_sec - time; - 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; - } - /* Give years and months for 5 years or so */ - if (diff < 1825) { - unsigned long years = (diff + 183) / 365; - unsigned long months = (diff % 365 + 15) / 30; - int n; - n = snprintf(timebuf, sizeof(timebuf), "%lu year%s", - years, (years > 1 ? "s" : "")); - if (months) - snprintf(timebuf + n, sizeof(timebuf) - n, - ", %lu month%s ago", - months, (months > 1 ? "s" : "")); - else - snprintf(timebuf + n, sizeof(timebuf) - n, - " ago"); - return timebuf; - } - /* Otherwise, just years. Centuries is probably overkill. */ - snprintf(timebuf, sizeof(timebuf), "%lu years ago", (diff + 183) / 365); - return timebuf; + return show_date_relative(time, tz, &now); } if (mode == DATE_LOCAL) @@ -866,19 +873,17 @@ static const char *approxidate_digit(const char *date, struct tm *tm, int *num) return end; } -unsigned long approxidate(const char *date) +unsigned long approxidate_relative(const char *date, const struct timeval *tv) { int number = 0; struct tm tm, now; - struct timeval tv; time_t time_sec; char buffer[50]; if (parse_date(date, buffer, sizeof(buffer)) > 0) return strtoul(buffer, NULL, 10); - gettimeofday(&tv, NULL); - time_sec = tv.tv_sec; + time_sec = tv->tv_sec; localtime_r(&time_sec, &tm); now = tm; for (;;) { @@ -899,3 +904,10 @@ unsigned long approxidate(const char *date) tm.tm_year--; return mktime(&tm); } + +unsigned long approxidate(const char *date) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return approxidate_relative(date, &tv); +} -- 1.6.4.1.261.gf9874 -- 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