* [PATCH 1/2] Add date formatting and parsing functions relative to a given time
@ 2009-08-28 21:04 Alex Riesen
2009-08-28 21:05 ` [PATCH 2/2] Allow testing of _relative family of time formatting and parsing functions Alex Riesen
2009-08-30 7:36 ` [PATCH 1/2] Add date formatting and parsing functions relative to a given time Jeff King
0 siblings, 2 replies; 10+ messages in thread
From: Alex Riesen @ 2009-08-28 21:04 UTC (permalink / raw)
To: git; +Cc: Jeff King, Nicolas Pitre, David Reiss, Junio C Hamano
The main purpose is to allow predictable testing of the code.
---
Rebased on current master.
cache.h | 2 +
date.c | 150 ++++++++++++++++++++++++++++++++++++--------------------------
2 files changed, 89 insertions(+), 63 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 f011692..0840e77 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 / 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 / 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,13 @@ static const char *approxidate_digit(const char *date, struct tm *tm, int *num)
return end;
}
-unsigned long approxidate(const char *date)
+static unsigned long approximation(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 +900,26 @@ unsigned long approxidate(const char *date)
tm.tm_year--;
return mktime(&tm);
}
+
+unsigned long approxidate_relative(const char *date, const struct timeval *tv)
+{
+ char buffer[50];
+
+ if (parse_date(date, buffer, sizeof(buffer)) > 0)
+ return strtoul(buffer, NULL, 10);
+
+ return approximation(date, tv);
+}
+
+unsigned long approxidate(const char *date)
+{
+ struct timeval tv;
+ char buffer[50];
+
+ if (parse_date(date, buffer, sizeof(buffer)) > 0)
+ return strtoul(buffer, NULL, 10);
+
+ gettimeofday(&tv, NULL);
+ return approximation(date, &tv);
+}
+
--
1.6.4.1.263.g468a
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/2] Allow testing of _relative family of time formatting and parsing functions
2009-08-28 21:04 [PATCH 1/2] Add date formatting and parsing functions relative to a given time Alex Riesen
@ 2009-08-28 21:05 ` Alex Riesen
2009-08-30 7:36 ` [PATCH 1/2] Add date formatting and parsing functions relative to a given time Jeff King
1 sibling, 0 replies; 10+ messages in thread
From: Alex Riesen @ 2009-08-28 21:05 UTC (permalink / raw)
To: git; +Cc: Jeff King, Nicolas Pitre, David Reiss, Junio C Hamano
To complement the testability of approxidate.
---
test-date.c | 17 +++++++++++++++++
1 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/test-date.c b/test-date.c
index 62e8f23..dcc7973 100644
--- a/test-date.c
+++ b/test-date.c
@@ -4,6 +4,17 @@ int main(int argc, char **argv)
{
int i;
+ struct tm tm;
+ struct timeval when = {0, 0};
+ tm.tm_sec = 0;
+ tm.tm_min = 0;
+ tm.tm_hour = 12;
+ tm.tm_mday = 1;
+ tm.tm_mon = 0 /* January */;
+ tm.tm_year = 90 /* 1990 */ ;
+ tm.tm_isdst = -1;
+ when.tv_sec = mktime(&tm);
+
for (i = 1; i < argc; i++) {
char result[100];
time_t t;
@@ -15,6 +26,12 @@ int main(int argc, char **argv)
t = approxidate(argv[i]);
printf("%s -> %s\n", argv[i], ctime(&t));
+
+ t = approxidate_relative(argv[i], &when);
+ printf("relative: %s -> %s\n", argv[i], ctime(&t));
+
+ printf("relative: %s, out of %s\n",
+ show_date_relative(t, 0, &when), ctime(&t));
}
return 0;
}
--
1.6.4.1.263.g468a
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] Add date formatting and parsing functions relative to a given time
2009-08-28 21:04 [PATCH 1/2] Add date formatting and parsing functions relative to a given time Alex Riesen
2009-08-28 21:05 ` [PATCH 2/2] Allow testing of _relative family of time formatting and parsing functions Alex Riesen
@ 2009-08-30 7:36 ` Jeff King
2009-08-30 7:51 ` Alex Riesen
1 sibling, 1 reply; 10+ messages in thread
From: Jeff King @ 2009-08-30 7:36 UTC (permalink / raw)
To: Alex Riesen; +Cc: git, Nicolas Pitre, David Reiss, Junio C Hamano
On Fri, Aug 28, 2009 at 11:04:04PM +0200, Alex Riesen wrote:
> +const char *show_date_relative(unsigned long time, int tz, const struct timeval *now)
> +{
> + static char timebuf[100 /* TODO: can be optimized */];
This was 200 in the original version. I doubt that it makes a
difference, but I think in a refactoring patch I think it is best to
simply reorganize and make no other changes.
> +static unsigned long approximation(const char *date, const struct timeval *tv)
I know it's static, but this is a terribly undescriptive function name.
Approximation of what? Can we call it approxidate_internal or
something?
-Peff
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] Add date formatting and parsing functions relative to a given time
2009-08-30 7:36 ` [PATCH 1/2] Add date formatting and parsing functions relative to a given time Jeff King
@ 2009-08-30 7:51 ` Alex Riesen
0 siblings, 0 replies; 10+ messages in thread
From: Alex Riesen @ 2009-08-30 7:51 UTC (permalink / raw)
To: Jeff King; +Cc: git, Nicolas Pitre, David Reiss, Junio C Hamano
On Sun, Aug 30, 2009 at 09:36, Jeff King<peff@peff.net> wrote:
> On Fri, Aug 28, 2009 at 11:04:04PM +0200, Alex Riesen wrote:
>
>> +const char *show_date_relative(unsigned long time, int tz, const struct timeval *now)
>> +{
>> + static char timebuf[100 /* TODO: can be optimized */];
>
> This was 200 in the original version. I doubt that it makes a
> difference, but I think in a refactoring patch I think it is best to
> simply reorganize and make no other changes.
Yes, I just noticed that 200 was much too much, made the note
to fix it sometime and forgot the note in the final submission.
>> +static unsigned long approximation(const char *date, const struct timeval *tv)
>
> I know it's static, but this is a terribly undescriptive function name.
> Approximation of what? Can we call it approxidate_internal or
> something?
Been there, tried that. Didn't like it, because it didn't feel enough
approxidate (the original) anymore. Not even internally, because
of missing parse_date. My other attempts were guessdate and
approxidate_bottom_half (but only very shortly).
The "approximation", if you consider the functions arguments,
seems to me the closest to what the function _is_. OTOH,
maybe I should have used a verb...
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Round-down years in "years+months" relative date view
@ 2009-08-28 7:58 Alex Riesen
2009-08-28 15:02 ` Jeff King
0 siblings, 1 reply; 10+ messages in thread
From: Alex Riesen @ 2009-08-28 7:58 UTC (permalink / raw)
To: Jeff King; +Cc: David Reiss, git
On Fri, Aug 28, 2009 at 08:05, Jeff King<peff@peff.net> wrote:
> On Thu, Aug 27, 2009 at 04:39:38PM -0700, David Reiss wrote:
>
>> Previously, a commit from 1 year and 7 months ago would display as
>> "2 years, 7 months ago".
>
> Wow, embarrassing.
>
> Acked-by: Jeff King <peff@peff.net>
>
>> Here's my test script. Let me know if you'd rather have it as part
>> of the test suite.
>
> 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:
$ git grep -n '"GIT_'| perl -ne '/"(GIT_\w+)/ && print "$1\n"' |
sort |uniq | wc -l
49
$ git grep -n '"GIT_'|grep ^Documentation
$
GIT_FLUSH? GIT_SEND_EMAIL_NOTTY?! GIT_CHERRY_PICK_HELP?!!
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Round-down years in "years+months" relative date view
2009-08-28 7:58 [PATCH] Round-down years in "years+months" relative date view Alex Riesen
@ 2009-08-28 15:02 ` Jeff King
2009-08-28 17:28 ` Nicolas Pitre
0 siblings, 1 reply; 10+ messages in thread
From: Jeff King @ 2009-08-28 15:02 UTC (permalink / raw)
To: Alex Riesen; +Cc: David Reiss, git
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.
-Peff
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Round-down years in "years+months" relative date view
2009-08-28 15:02 ` Jeff King
@ 2009-08-28 17:28 ` Nicolas Pitre
2009-08-28 19:03 ` Alex Riesen
0 siblings, 1 reply; 10+ messages in thread
From: Nicolas Pitre @ 2009-08-28 17:28 UTC (permalink / raw)
To: Jeff King; +Cc: Alex Riesen, David Reiss, git
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.
However I was hoping for a current time trickery solution that could
live in test-date.c instead of interfering with the main code in such a
way.
Did a quick test to override the library version:
diff --git a/test-date.c b/test-date.c
index 62e8f23..0bcd0c9 100644
--- a/test-date.c
+++ b/test-date.c
@@ -1,5 +1,10 @@
#include "cache.h"
+int gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ return 0;
+}
+
int main(int argc, char **argv)
{
int i;
Result:
$ ./test-date now
now -> bad -> Wed Dec 31 19:00:00 1969
now -> Tue Jan 22 10:48:24 10199
So this seems to work. ;-)
Nicolas
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] Round-down years in "years+months" relative date view
2009-08-28 17:28 ` Nicolas Pitre
@ 2009-08-28 19:03 ` Alex Riesen
2009-08-28 19:15 ` Jeff King
0 siblings, 1 reply; 10+ messages in thread
From: Alex Riesen @ 2009-08-28 19:03 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: Jeff King, David Reiss, git
>From b51bc56816490c71cd37f52be73a06cef6b9bf14 Mon Sep 17 00:00:00 2001
From: Alex Riesen <raa.lkml@gmail.com>
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
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] Round-down years in "years+months" relative date view
2009-08-28 19:03 ` Alex Riesen
@ 2009-08-28 19:15 ` Jeff King
2009-08-28 19:20 ` Alex Riesen
0 siblings, 1 reply; 10+ messages in thread
From: Jeff King @ 2009-08-28 19:15 UTC (permalink / raw)
To: Alex Riesen; +Cc: Nicolas Pitre, David Reiss, git
On Fri, Aug 28, 2009 at 09:03:19PM +0200, Alex Riesen wrote:
> +unsigned long approxidate(const char *date)
> +{
> + struct timeval tv;
> + gettimeofday(&tv, NULL);
> + return approxidate_relative(date, &tv);
> +}
This now always calls gettimeofday, whereas the original approxidate
only did if parse_date failed.
I think you could also make this patch much smaller by just wrapping the
whole function and using a '0' sentinel for "you need to fill in the
time." Like:
---
diff --git a/date.c b/date.c
index 409a17d..b084d19 100644
--- a/date.c
+++ b/date.c
@@ -86,6 +86,14 @@ static int local_tzoffset(unsigned long time)
const char *show_date(unsigned long time, int tz, enum date_mode mode)
{
+ struct timeval now;
+ now.tv_sec = 0;
+ show_date_at_time(time, tz, mode, &now);
+}
+
+const char *show_date_at_time(unsigned long time, int tz, enum date_mode mode,
+ struct timeval now)
+{
struct tm *tm;
static char timebuf[200];
@@ -96,8 +104,8 @@ 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)
+ gettimeofday(&now, NULL);
if (now.tv_sec < time)
return "in the future";
diff = now.tv_sec - time;
On the other hand, refactoring the relative date code into its own
function is probably a good thing in the long run.
-Peff
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] Round-down years in "years+months" relative date view
2009-08-28 19:15 ` Jeff King
@ 2009-08-28 19:20 ` Alex Riesen
2009-08-28 19:33 ` Alex Riesen
0 siblings, 1 reply; 10+ messages in thread
From: Alex Riesen @ 2009-08-28 19:20 UTC (permalink / raw)
To: Jeff King; +Cc: Nicolas Pitre, David Reiss, git
On Fri, Aug 28, 2009 at 21:15, Jeff King<peff@peff.net> wrote:
> On Fri, Aug 28, 2009 at 09:03:19PM +0200, Alex Riesen wrote:
>
>> +unsigned long approxidate(const char *date)
>> +{
>> + struct timeval tv;
>> + gettimeofday(&tv, NULL);
>> + return approxidate_relative(date, &tv);
>> +}
>
> This now always calls gettimeofday, whereas the original approxidate
> only did if parse_date failed.
Oh, bugger...
> On the other hand, refactoring the relative date code into its own
> function is probably a good thing in the long run.
Exactly.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Round-down years in "years+months" relative date view
2009-08-28 19:20 ` Alex Riesen
@ 2009-08-28 19:33 ` Alex Riesen
2009-08-28 20:52 ` [PATCH] Allow testing of _relative family of time formatting and parsing functions Alex Riesen
0 siblings, 1 reply; 10+ messages in thread
From: Alex Riesen @ 2009-08-28 19:33 UTC (permalink / raw)
To: Jeff King; +Cc: Nicolas Pitre, David Reiss, git
From fe67532bdf095dc9ebc0c7dd67be384e807a197c Mon Sep 17 00:00:00 2001
From: Alex Riesen <raa.lkml@gmail.com>
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.
---
Alex Riesen, Fri, Aug 28, 2009 21:20:50 +0200:
> On Fri, Aug 28, 2009 at 21:15, Jeff King<peff@peff.net> wrote:
> > On Fri, Aug 28, 2009 at 09:03:19PM +0200, Alex Riesen wrote:
> >
> >> +unsigned long approxidate(const char *date)
> >> +{
> >> + struct timeval tv;
> >> + gettimeofday(&tv, NULL);
> >> + return approxidate_relative(date, &tv);
> >> +}
> >
> > This now always calls gettimeofday, whereas the original approxidate
> > only did if parse_date failed.
>
> Oh, bugger...
>
Rather like this, I mean :)
cache.h | 2 +
date.c | 150 ++++++++++++++++++++++++++++++++++++--------------------------
2 files changed, 89 insertions(+), 63 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..171e68f 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,13 @@ static const char *approxidate_digit(const char *date, struct tm *tm, int *num)
return end;
}
-unsigned long approxidate(const char *date)
+static unsigned long approximation(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 +900,26 @@ unsigned long approxidate(const char *date)
tm.tm_year--;
return mktime(&tm);
}
+
+unsigned long approxidate_relative(const char *date, const struct timeval *tv)
+{
+ char buffer[50];
+
+ if (parse_date(date, buffer, sizeof(buffer)) > 0)
+ return strtoul(buffer, NULL, 10);
+
+ return approximation(date, tv);
+}
+
+unsigned long approxidate(const char *date)
+{
+ struct timeval tv;
+ char buffer[50];
+
+ if (parse_date(date, buffer, sizeof(buffer)) > 0)
+ return strtoul(buffer, NULL, 10);
+
+ gettimeofday(&tv, NULL);
+ return approximation(date, &tv);
+}
+
--
1.6.4.1.261.gf9874
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH] Allow testing of _relative family of time formatting and parsing functions
2009-08-28 19:33 ` Alex Riesen
@ 2009-08-28 20:52 ` Alex Riesen
2009-08-29 21:46 ` Junio C Hamano
0 siblings, 1 reply; 10+ messages in thread
From: Alex Riesen @ 2009-08-28 20:52 UTC (permalink / raw)
To: Jeff King; +Cc: Nicolas Pitre, David Reiss, git
To complement the testability of approxidate.
---
Alex Riesen, Fri, Aug 28, 2009 21:33:02 +0200:
>
> It should allow safe testing of this part of the code.
And this should really allow testing of it:
$ ./test-date '10.days.ago'
10.days.ago -> bad -> Thu Jan 1 01:00:00 1970
10.days.ago -> Tue Aug 18 22:50:20 2009
relative: 10.days.ago -> Fri Dec 22 12:00:00 1989
relative: 10 days ago, out of Fri Dec 22 12:00:00 1989
$
According to Wikipedia, absolutely nothing of note happened
at the day 10 January, 1990.
test-date.c | 17 +++++++++++++++++
1 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/test-date.c b/test-date.c
index 62e8f23..dcc7973 100644
--- a/test-date.c
+++ b/test-date.c
@@ -4,6 +4,17 @@ int main(int argc, char **argv)
{
int i;
+ struct tm tm;
+ struct timeval when = {0, 0};
+ tm.tm_sec = 0;
+ tm.tm_min = 0;
+ tm.tm_hour = 12;
+ tm.tm_mday = 1;
+ tm.tm_mon = 0 /* January */;
+ tm.tm_year = 90 /* 1990 */ ;
+ tm.tm_isdst = -1;
+ when.tv_sec = mktime(&tm);
+
for (i = 1; i < argc; i++) {
char result[100];
time_t t;
@@ -15,6 +26,12 @@ int main(int argc, char **argv)
t = approxidate(argv[i]);
printf("%s -> %s\n", argv[i], ctime(&t));
+
+ t = approxidate_relative(argv[i], &when);
+ printf("relative: %s -> %s\n", argv[i], ctime(&t));
+
+ printf("relative: %s, out of %s\n",
+ show_date_relative(t, 0, &when), ctime(&t));
}
return 0;
}
--
1.6.4.1.263.g468a
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] Allow testing of _relative family of time formatting and parsing functions
2009-08-28 20:52 ` [PATCH] Allow testing of _relative family of time formatting and parsing functions Alex Riesen
@ 2009-08-29 21:46 ` Junio C Hamano
2009-08-30 7:25 ` Alex Riesen
0 siblings, 1 reply; 10+ messages in thread
From: Junio C Hamano @ 2009-08-29 21:46 UTC (permalink / raw)
To: Alex Riesen; +Cc: Jeff King, Nicolas Pitre, David Reiss, git
Alex Riesen <raa.lkml@gmail.com> writes:
> To complement the testability of approxidate.
> ---
> Alex Riesen, Fri, Aug 28, 2009 21:33:02 +0200:
>>
>> It should allow safe testing of this part of the code.
>
> And this should really allow testing of it:
>
> $ ./test-date '10.days.ago'
> 10.days.ago -> bad -> Thu Jan 1 01:00:00 1970
> 10.days.ago -> Tue Aug 18 22:50:20 2009
>
> relative: 10.days.ago -> Fri Dec 22 12:00:00 1989
>
> relative: 10 days ago, out of Fri Dec 22 12:00:00 1989
>
> $
What are these blank lines for? Is this intended as a serious submission
for inclusion? I am having a hrad time to guess, especially you did not
sign this off, nor Cc'ed me.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Allow testing of _relative family of time formatting and parsing functions
2009-08-29 21:46 ` Junio C Hamano
@ 2009-08-30 7:25 ` Alex Riesen
2009-08-30 9:13 ` [PATCH 1/2] Add date formatting and parsing functions relative to a given time Alex Riesen
0 siblings, 1 reply; 10+ messages in thread
From: Alex Riesen @ 2009-08-30 7:25 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, Nicolas Pitre, David Reiss, git
On Sat, Aug 29, 2009 at 23:46, Junio C Hamano<gitster@pobox.com> wrote:
> Alex Riesen <raa.lkml@gmail.com> writes:
>> To complement the testability of approxidate.
>> ---
>> Alex Riesen, Fri, Aug 28, 2009 21:33:02 +0200:
>>>
>>> It should allow safe testing of this part of the code.
>>
>> And this should really allow testing of it:
>>
>> $ ./test-date '10.days.ago'
>> 10.days.ago -> bad -> Thu Jan 1 01:00:00 1970
>> 10.days.ago -> Tue Aug 18 22:50:20 2009
>>
>> relative: 10.days.ago -> Fri Dec 22 12:00:00 1989
>>
>> relative: 10 days ago, out of Fri Dec 22 12:00:00 1989
>>
>> $
>
> What are these blank lines for?
ctime(3) artifact (it adds a \n in the output buffer), which I missed.
> Is this intended as a serious submission for inclusion?
Not yet. AFAICS, test-date is never used in our test suite.
> I am having a hrad time to guess, especially you did not
> sign this off, nor Cc'ed me.
Right, that's because I'm not sure myself. Frankly, I'm not
convinced we have to test every single thing. In my experience,
the bigger a test suite, the less are people inclined to use it
(including setting up automatic test runs).
Jeff, Nicolas? Is this test enough? Are there any other code
paths you want to include in the test?
And sorry for having you missed in Cc:, that wasn't intended.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/2] Add date formatting and parsing functions relative to a given time
2009-08-30 7:25 ` Alex Riesen
@ 2009-08-30 9:13 ` Alex Riesen
2009-08-30 9:15 ` Jeff King
0 siblings, 1 reply; 10+ messages in thread
From: Alex Riesen @ 2009-08-30 9:13 UTC (permalink / raw)
To: git; +Cc: Jeff King, Nicolas Pitre, David Reiss, Junio C Hamano
The main purpose is to allow predictable testing of the code.
Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
---
Have show_date_relative supplied the output buffer. As it is a new
interface, it can as well be a little bit more generic than its sole
caller. test-date.c is updated and shall follow in a moment.
And, after a while thinking, I am convinced that Jeff has a point
and used a more "internal" name for approxidate's recent "bottom half".
cache.h | 5 ++
date.c | 152 +++++++++++++++++++++++++++++++++++++--------------------------
2 files changed, 94 insertions(+), 63 deletions(-)
diff --git a/cache.h b/cache.h
index dd7f71e..1586f33 100644
--- a/cache.h
+++ b/cache.h
@@ -731,9 +731,14 @@ 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,
+ char *timebuf,
+ size_t timebuf_size);
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 f011692..0b0f7a7 100644
--- a/date.c
+++ b/date.c
@@ -84,6 +84,68 @@ static int local_tzoffset(unsigned long time)
return offset * eastwest;
}
+const char *show_date_relative(unsigned long time, int tz,
+ const struct timeval *now,
+ char *timebuf,
+ size_t timebuf_size)
+{
+ unsigned long diff;
+ if (now->tv_sec < time)
+ return "in the future";
+ diff = now->tv_sec - time;
+ if (diff < 90) {
+ snprintf(timebuf, timebuf_size, "%lu seconds ago", diff);
+ return timebuf;
+ }
+ /* Turn it into minutes */
+ diff = (diff + 30) / 60;
+ if (diff < 90) {
+ snprintf(timebuf, timebuf_size, "%lu minutes ago", diff);
+ return timebuf;
+ }
+ /* Turn it into hours */
+ diff = (diff + 30) / 60;
+ if (diff < 36) {
+ snprintf(timebuf, timebuf_size, "%lu hours ago", diff);
+ return timebuf;
+ }
+ /* We deal with number of days from here on */
+ diff = (diff + 12) / 24;
+ if (diff < 14) {
+ snprintf(timebuf, timebuf_size, "%lu days ago", diff);
+ return timebuf;
+ }
+ /* Say weeks for the past 10 weeks or so */
+ if (diff < 70) {
+ snprintf(timebuf, timebuf_size, "%lu weeks ago", (diff + 3) / 7);
+ return timebuf;
+ }
+ /* Say months for the past 12 months or so */
+ if (diff < 360) {
+ snprintf(timebuf, timebuf_size, "%lu months ago", (diff + 15) / 30);
+ return timebuf;
+ }
+ /* Give years and months for 5 years or so */
+ if (diff < 1825) {
+ unsigned long years = diff / 365;
+ unsigned long months = (diff % 365 + 15) / 30;
+ int n;
+ n = snprintf(timebuf, timebuf_size, "%lu year%s",
+ years, (years > 1 ? "s" : ""));
+ if (months)
+ snprintf(timebuf + n, timebuf_size - n,
+ ", %lu month%s ago",
+ months, (months > 1 ? "s" : ""));
+ else
+ snprintf(timebuf + n, timebuf_size - n,
+ " ago");
+ return timebuf;
+ }
+ /* Otherwise, just years. Centuries is probably overkill. */
+ snprintf(timebuf, timebuf_size, "%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 +157,10 @@ 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 / 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,
+ timebuf, sizeof(timebuf));
}
if (mode == DATE_LOCAL)
@@ -866,19 +875,13 @@ static const char *approxidate_digit(const char *date, struct tm *tm, int *num)
return end;
}
-unsigned long approxidate(const char *date)
+static unsigned long approxidate_str(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 +902,26 @@ unsigned long approxidate(const char *date)
tm.tm_year--;
return mktime(&tm);
}
+
+unsigned long approxidate_relative(const char *date, const struct timeval *tv)
+{
+ char buffer[50];
+
+ if (parse_date(date, buffer, sizeof(buffer)) > 0)
+ return strtoul(buffer, NULL, 10);
+
+ return approxidate_str(date, tv);
+}
+
+unsigned long approxidate(const char *date)
+{
+ struct timeval tv;
+ char buffer[50];
+
+ if (parse_date(date, buffer, sizeof(buffer)) > 0)
+ return strtoul(buffer, NULL, 10);
+
+ gettimeofday(&tv, NULL);
+ return approxidate_str(date, &tv);
+}
+
--
1.6.4.1.294.g16262
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] Add date formatting and parsing functions relative to a given time
2009-08-30 9:13 ` [PATCH 1/2] Add date formatting and parsing functions relative to a given time Alex Riesen
@ 2009-08-30 9:15 ` Jeff King
2009-08-30 9:36 ` Jeff King
0 siblings, 1 reply; 10+ messages in thread
From: Jeff King @ 2009-08-30 9:15 UTC (permalink / raw)
To: Alex Riesen; +Cc: git, Nicolas Pitre, David Reiss, Junio C Hamano
On Sun, Aug 30, 2009 at 11:13:46AM +0200, Alex Riesen wrote:
> Have show_date_relative supplied the output buffer. As it is a new
> interface, it can as well be a little bit more generic than its sole
> caller. test-date.c is updated and shall follow in a moment.
FYI, I am munging test-date to match the test script I am writing, so
don't bother with that patch.
-Peff
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] Add date formatting and parsing functions relative to a given time
2009-08-30 9:15 ` Jeff King
@ 2009-08-30 9:36 ` Jeff King
2009-08-30 9:56 ` Alex Riesen
0 siblings, 1 reply; 10+ messages in thread
From: Jeff King @ 2009-08-30 9:36 UTC (permalink / raw)
To: Alex Riesen; +Cc: git, Nicolas Pitre, David Reiss, Junio C Hamano
On Sun, Aug 30, 2009 at 05:15:57AM -0400, Jeff King wrote:
> FYI, I am munging test-date to match the test script I am writing, so
> don't bother with that patch.
Here is what my patch is looking like. Please give any comments, and
then I will resubmit in a form that will be simpler for Junio, which
should be a series with:
- your patch to refactor date.c
- this patch (this version uses the original interface to
show_relative; I will tweak to match the new patch you just sent)
- another patch to go on top of lt/approxidate to test recent fixes
from Linus
---
diff --git a/t/t0006-date.sh b/t/t0006-date.sh
new file mode 100755
index 0000000..4beb44b
--- /dev/null
+++ b/t/t0006-date.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+test_description='test date parsing and printing'
+. ./test-lib.sh
+
+# arbitrary reference time: 2009-08-30 19:20:00
+TEST_DATE_NOW=1251660000; export TEST_DATE_NOW
+
+check_show() {
+ t=$(($TEST_DATE_NOW - $1))
+ echo "$t -> $2" >expect
+ test_expect_success "relative date ($2)" "
+ test-date show $t >actual &&
+ test_cmp expect actual
+ "
+}
+
+check_show 5 '5 seconds ago'
+check_show 300 '5 minutes ago'
+check_show 18000 '5 hours ago'
+check_show 432000 '5 days ago'
+check_show 1728000 '3 weeks ago'
+check_show 13000000 '5 months ago'
+check_show 37500000 '1 year, 2 months ago'
+check_show 55188000 '1 year, 9 months ago'
+check_show 630000000 '20 years ago'
+
+check_parse() {
+ echo "$1 -> $2" >expect
+ test_expect_success "parse date ($1)" "
+ test-date parse '$1' >actual &&
+ test_cmp expect actual
+ "
+}
+
+check_parse 2008 bad
+check_parse 2008-02 bad
+check_parse 2008-02-14 '2008-02-14 00:00:00 +0000'
+check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 +0000'
+
+check_approxidate() {
+ echo "$1 -> $2 +0000" >expect
+ test_expect_success "parse approxidate ($1)" "
+ test-date approxidate '$1' >actual &&
+ test_cmp expect actual
+ "
+}
+
+check_approxidate now '2009-08-30 19:20:00'
+check_approxidate '5 seconds ago' '2009-08-30 19:19:55'
+check_approxidate 5.seconds.ago '2009-08-30 19:19:55'
+check_approxidate 10.minutes.ago '2009-08-30 19:10:00'
+check_approxidate yesterday '2009-08-29 19:20:00'
+check_approxidate 3.days.ago '2009-08-27 19:20:00'
+check_approxidate 3.weeks.ago '2009-08-09 19:20:00'
+check_approxidate 3.months.ago '2009-05-30 19:20:00'
+check_approxidate 2.years.3.months.ago '2007-05-30 19:20:00'
+
+check_approxidate '6am yesterday' '2009-08-29 06:00:00'
+check_approxidate '6pm yesterday' '2009-08-29 18:00:00'
+check_approxidate '3:00' '2009-08-30 03:00:00'
+check_approxidate '15:00' '2009-08-30 15:00:00'
+check_approxidate 'noon today' '2009-08-30 12:00:00'
+check_approxidate 'noon yesterday' '2009-08-29 12:00:00'
+
+check_approxidate 'last tuesday' '2009-08-25 19:20:00'
+check_approxidate 'July 5th' '2009-07-05 19:20:00'
+check_approxidate '06/05/2009' '2009-06-05 00:00:00'
+check_approxidate '06.05.2009' '2009-05-06 00:00:00'
+
+test_done
diff --git a/test-date.c b/test-date.c
index 62e8f23..8d263a3 100644
--- a/test-date.c
+++ b/test-date.c
@@ -1,20 +1,63 @@
#include "cache.h"
-int main(int argc, char **argv)
+static const char *usage_msg = "\n"
+" test-date show [time_t]...\n"
+" test-date parse [date]...\n"
+" test-date approxidate [date]...\n";
+
+static void show_dates(char **argv, struct timeval *now)
{
- int i;
+ for (; *argv; argv++) {
+ time_t t = atoi(*argv);
+ printf("%s -> %s\n", *argv, show_date_relative(t, 0, now));
+ }
+}
- for (i = 1; i < argc; i++) {
+static void parse_dates(char **argv, struct timeval *now)
+{
+ for (; *argv; argv++) {
char result[100];
time_t t;
- memcpy(result, "bad", 4);
- parse_date(argv[i], result, sizeof(result));
+ parse_date(*argv, result, sizeof(result));
t = strtoul(result, NULL, 0);
- printf("%s -> %s -> %s", argv[i], result, ctime(&t));
+ printf("%s -> %s\n", *argv,
+ t ? show_date(t, 0, DATE_ISO8601) : "bad");
+ }
+}
+
+static void parse_approxidate(char **argv, struct timeval *now)
+{
+ for (; *argv; argv++) {
+ time_t t;
+ t = approxidate_relative(*argv, now);
+ printf("%s -> %s\n", *argv, show_date(t, 0, DATE_ISO8601));
+ }
+}
- t = approxidate(argv[i]);
- printf("%s -> %s\n", argv[i], ctime(&t));
+int main(int argc, char **argv)
+{
+ struct timeval now;
+ const char *x;
+
+ x = getenv("TEST_DATE_NOW");
+ if (x) {
+ now.tv_sec = atoi(x);
+ now.tv_usec = 0;
}
+ else
+ gettimeofday(&now, NULL);
+
+ argv++;
+ if (!*argv)
+ usage(usage_msg);
+ if (!strcmp(*argv, "show"))
+ show_dates(argv+1, &now);
+ else if (!strcmp(*argv, "parse"))
+ parse_dates(argv+1, &now);
+ else if (!strcmp(*argv, "approxidate"))
+ parse_approxidate(argv+1, &now);
+ else
+ usage(usage_msg);
return 0;
}
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] Add date formatting and parsing functions relative to a given time
2009-08-30 9:36 ` Jeff King
@ 2009-08-30 9:56 ` Alex Riesen
2009-08-30 10:08 ` Jeff King
0 siblings, 1 reply; 10+ messages in thread
From: Alex Riesen @ 2009-08-30 9:56 UTC (permalink / raw)
To: Jeff King; +Cc: git, Nicolas Pitre, David Reiss, Junio C Hamano
On Sun, Aug 30, 2009 at 11:36, Jeff King<peff@peff.net> wrote:
> On Sun, Aug 30, 2009 at 05:15:57AM -0400, Jeff King wrote:
>
>> FYI, I am munging test-date to match the test script I am writing, so
>> don't bother with that patch.
>
> Here is what my patch is looking like. Please give any comments, and
> then I will resubmit in a form that will be simpler for Junio, which
> should be a series with:
>
> - your patch to refactor date.c
> - this patch (this version uses the original interface to
> show_relative; I will tweak to match the new patch you just sent)
Yes, I think this is the only comment I can make.
> +# arbitrary reference time: 2009-08-30 19:20:00
The world changed since 1980 :) There is already three things
happened at the day (http://en.wikipedia.org/wiki/August_2009),
and it is not evening yet (well, here in Europe)
> +check_show 5 '5 seconds ago'
> +check_show 300 '5 minutes ago'
> +check_show 18000 '5 hours ago'
> +check_show 432000 '5 days ago'
> +check_show 1728000 '3 weeks ago'
> +check_show 13000000 '5 months ago'
> +check_show 37500000 '1 year, 2 months ago'
> +check_show 55188000 '1 year, 9 months ago'
> +check_show 630000000 '20 years ago'
check_show 630000000 '20.years.ago'?
(Arbitrary, non-whitespace delimiters, which was an
advertised feature, to make shell's life easier)
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] Add date formatting and parsing functions relative to a given time
2009-08-30 9:56 ` Alex Riesen
@ 2009-08-30 10:08 ` Jeff King
2009-08-30 11:17 ` Alex Riesen
0 siblings, 1 reply; 10+ messages in thread
From: Jeff King @ 2009-08-30 10:08 UTC (permalink / raw)
To: Alex Riesen; +Cc: git, Nicolas Pitre, David Reiss, Junio C Hamano
On Sun, Aug 30, 2009 at 11:56:37AM +0200, Alex Riesen wrote:
> > +check_show 5 '5 seconds ago'
> > +check_show 300 '5 minutes ago'
> > +check_show 18000 '5 hours ago'
> > +check_show 432000 '5 days ago'
> > +check_show 1728000 '3 weeks ago'
> > +check_show 13000000 '5 months ago'
> > +check_show 37500000 '1 year, 2 months ago'
> > +check_show 55188000 '1 year, 9 months ago'
> > +check_show 630000000 '20 years ago'
>
> check_show 630000000 '20.years.ago'?
> (Arbitrary, non-whitespace delimiters, which was an
> advertised feature, to make shell's life easier)
This part is about checking what show_date produces (the first number is
an offset from now in seconds, and the second is what we expect), so it
always has spaces.
See the check_approxidate section further down for an example of parsing
what you are talking about.
-Peff
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] Add date formatting and parsing functions relative to a given time
2009-08-30 10:08 ` Jeff King
@ 2009-08-30 11:17 ` Alex Riesen
0 siblings, 0 replies; 10+ messages in thread
From: Alex Riesen @ 2009-08-30 11:17 UTC (permalink / raw)
To: Jeff King; +Cc: git, Nicolas Pitre, David Reiss, Junio C Hamano
On Sun, Aug 30, 2009 at 12:08, Jeff King<peff@peff.net> wrote:
> On Sun, Aug 30, 2009 at 11:56:37AM +0200, Alex Riesen wrote:
>>
>> check_show 630000000 '20.years.ago'?
>> (Arbitrary, non-whitespace delimiters, which was an
>> advertised feature, to make shell's life easier)
>
> This part is about checking what show_date produces (the first number is
> an offset from now in seconds, and the second is what we expect), so it
> always has spaces.
>
> See the check_approxidate section further down for an example of parsing
> what you are talking about.
Ah, I see
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2009-08-30 11:17 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-08-28 21:04 [PATCH 1/2] Add date formatting and parsing functions relative to a given time Alex Riesen
2009-08-28 21:05 ` [PATCH 2/2] Allow testing of _relative family of time formatting and parsing functions Alex Riesen
2009-08-30 7:36 ` [PATCH 1/2] Add date formatting and parsing functions relative to a given time Jeff King
2009-08-30 7:51 ` Alex Riesen
-- strict thread matches above, loose matches on Subject: below --
2009-08-28 7:58 [PATCH] Round-down years in "years+months" relative date view Alex Riesen
2009-08-28 15:02 ` Jeff King
2009-08-28 17:28 ` Nicolas Pitre
2009-08-28 19:03 ` Alex Riesen
2009-08-28 19:15 ` Jeff King
2009-08-28 19:20 ` Alex Riesen
2009-08-28 19:33 ` Alex Riesen
2009-08-28 20:52 ` [PATCH] Allow testing of _relative family of time formatting and parsing functions Alex Riesen
2009-08-29 21:46 ` Junio C Hamano
2009-08-30 7:25 ` Alex Riesen
2009-08-30 9:13 ` [PATCH 1/2] Add date formatting and parsing functions relative to a given time Alex Riesen
2009-08-30 9:15 ` Jeff King
2009-08-30 9:36 ` Jeff King
2009-08-30 9:56 ` Alex Riesen
2009-08-30 10:08 ` Jeff King
2009-08-30 11:17 ` Alex Riesen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).