Add date formatting and parsing functions relative to a given time
The main purpose is to allow predictable testing of the code. Signed-off-by: Alex Riesen <raa.lkml@gmail.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
36e4986f26
commit
33012fc429
5
cache.h
5
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(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);
|
int parse_date(const char *date, char *buf, int bufsize);
|
||||||
void datestamp(char *buf, int bufsize);
|
void datestamp(char *buf, int bufsize);
|
||||||
unsigned long approxidate(const char *);
|
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);
|
enum date_mode parse_date_format(const char *format);
|
||||||
|
|
||||||
#define IDENT_WARN_ON_NO_NAME 1
|
#define IDENT_WARN_ON_NO_NAME 1
|
||||||
|
150
date.c
150
date.c
@ -86,6 +86,67 @@ static int local_tzoffset(unsigned long time)
|
|||||||
return offset * eastwest;
|
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)
|
const char *show_date(unsigned long time, int tz, enum date_mode mode)
|
||||||
{
|
{
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
@ -97,63 +158,10 @@ const char *show_date(unsigned long time, int tz, enum date_mode mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mode == DATE_RELATIVE) {
|
if (mode == DATE_RELATIVE) {
|
||||||
unsigned long diff;
|
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
if (now.tv_sec < time)
|
return show_date_relative(time, tz, &now,
|
||||||
return "in the future";
|
timebuf, sizeof(timebuf));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == DATE_LOCAL)
|
if (mode == DATE_LOCAL)
|
||||||
@ -918,19 +926,13 @@ static void pending_number(struct tm *tm, int *num)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long approxidate(const char *date)
|
static unsigned long approxidate_str(const char *date, const struct timeval *tv)
|
||||||
{
|
{
|
||||||
int number = 0;
|
int number = 0;
|
||||||
struct tm tm, now;
|
struct tm tm, now;
|
||||||
struct timeval tv;
|
|
||||||
time_t time_sec;
|
time_t time_sec;
|
||||||
char buffer[50];
|
|
||||||
|
|
||||||
if (parse_date(date, buffer, sizeof(buffer)) > 0)
|
time_sec = tv->tv_sec;
|
||||||
return strtoul(buffer, NULL, 10);
|
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
time_sec = tv.tv_sec;
|
|
||||||
localtime_r(&time_sec, &tm);
|
localtime_r(&time_sec, &tm);
|
||||||
now = tm;
|
now = tm;
|
||||||
|
|
||||||
@ -954,3 +956,25 @@ unsigned long approxidate(const char *date)
|
|||||||
pending_number(&tm, &number);
|
pending_number(&tm, &number);
|
||||||
return update_tm(&tm, &now, 0);
|
return update_tm(&tm, &now, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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, 0);
|
||||||
|
|
||||||
|
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, 0);
|
||||||
|
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return approxidate_str(date, &tv);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user