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>
Alex Riesen committed
Aug 30, 2009 at 22:26 UTC
33012fc429af24fee64f39406d401662feb947a8
2 files changed
+92
-63
cache.h
+5
@@ -731,9 +731,14 @@ enum date_mode {
731
};
732
733
const char *show_date(unsigned long time, int timezone, enum date_mode mode);
734
+const char *show_date_relative(unsigned long time, int tz,
735
+ const struct timeval *now,
736
+ char *timebuf,
737
+ size_t timebuf_size);
738
int parse_date(const char *date, char *buf, int bufsize);
739
void datestamp(char *buf, int bufsize);
740
unsigned long approxidate(const char *);
741
+unsigned long approxidate_relative(const char *date, const struct timeval *now);
742
enum date_mode parse_date_format(const char *format);
743
744
#define IDENT_WARN_ON_NO_NAME 1
date.c
+87
-63
@@ -86,6 +86,67 @@ static int local_tzoffset(unsigned long time)
86
return offset * eastwest;
87
}
88
89
+const char *show_date_relative(unsigned long time, int tz,
90
+ const struct timeval *now,
91
+ char *timebuf,
92
+ size_t timebuf_size)
93
+{
94
+ unsigned long diff;
95
+ if (now->tv_sec < time)
96
+ return "in the future";
97
+ diff = now->tv_sec - time;
98
+ if (diff < 90) {
99
+ snprintf(timebuf, timebuf_size, "%lu seconds ago", diff);
100
+ return timebuf;
101
+ }
102
+ /* Turn it into minutes */
103
+ diff = (diff + 30) / 60;
104
+ if (diff < 90) {
105
+ snprintf(timebuf, timebuf_size, "%lu minutes ago", diff);
106
+ return timebuf;
107
+ }
108
+ /* Turn it into hours */
109
+ diff = (diff + 30) / 60;
110
+ if (diff < 36) {
111
+ snprintf(timebuf, timebuf_size, "%lu hours ago", diff);
112
+ return timebuf;
113
+ }
114
+ /* We deal with number of days from here on */
115
+ diff = (diff + 12) / 24;
116
+ if (diff < 14) {
117
+ snprintf(timebuf, timebuf_size, "%lu days ago", diff);
118
+ return timebuf;
119
+ }
120
+ /* Say weeks for the past 10 weeks or so */
121
+ if (diff < 70) {
122
+ snprintf(timebuf, timebuf_size, "%lu weeks ago", (diff + 3) / 7);
123
+ return timebuf;
124
+ }
125
+ /* Say months for the past 12 months or so */
126
+ if (diff < 360) {
127
+ snprintf(timebuf, timebuf_size, "%lu months ago", (diff + 15) / 30);
128
+ return timebuf;
129
+ }
130
+ /* Give years and months for 5 years or so */
131
+ if (diff < 1825) {
132
+ unsigned long years = diff / 365;
133
+ unsigned long months = (diff % 365 + 15) / 30;
134
+ int n;
135
+ n = snprintf(timebuf, timebuf_size, "%lu year%s",
136
+ years, (years > 1 ? "s" : ""));
137
+ if (months)
138
+ snprintf(timebuf + n, timebuf_size - n,
139
+ ", %lu month%s ago",
140
+ months, (months > 1 ? "s" : ""));
141
+ else
142
+ snprintf(timebuf + n, timebuf_size - n, " ago");
143
+ return timebuf;
144
+ }
145
+ /* Otherwise, just years. Centuries is probably overkill. */
146
+ snprintf(timebuf, timebuf_size, "%lu years ago", (diff + 183) / 365);
147
+ return timebuf;
148
+}
149
+
150
const char *show_date(unsigned long time, int tz, enum date_mode mode)
151
{
152
struct tm *tm;
@@ -97,63 +158,10 @@ const char *show_date(unsigned long time, int tz, enum date_mode mode)
158
}
159
160
if (mode == DATE_RELATIVE) {
100
- unsigned long diff;
161
struct timeval now;
162
gettimeofday(&now, NULL);
103
- if (now.tv_sec < time)
104
- return "in the future";
105
- diff = now.tv_sec - time;
106
- if (diff < 90) {
107
- snprintf(timebuf, sizeof(timebuf), "%lu seconds ago", diff);
108
- return timebuf;
109
- }
110
- /* Turn it into minutes */
111
- diff = (diff + 30) / 60;
112
- if (diff < 90) {
113
- snprintf(timebuf, sizeof(timebuf), "%lu minutes ago", diff);
114
- return timebuf;
115
- }
116
- /* Turn it into hours */
117
- diff = (diff + 30) / 60;
118
- if (diff < 36) {
119
- snprintf(timebuf, sizeof(timebuf), "%lu hours ago", diff);
120
- return timebuf;
121
- }
122
- /* We deal with number of days from here on */
123
- diff = (diff + 12) / 24;
124
- if (diff < 14) {
125
- snprintf(timebuf, sizeof(timebuf), "%lu days ago", diff);
126
- return timebuf;
127
- }
128
- /* Say weeks for the past 10 weeks or so */
129
- if (diff < 70) {
130
- snprintf(timebuf, sizeof(timebuf), "%lu weeks ago", (diff + 3) / 7);
131
- return timebuf;
132
- }
133
- /* Say months for the past 12 months or so */
134
- if (diff < 360) {
135
- snprintf(timebuf, sizeof(timebuf), "%lu months ago", (diff + 15) / 30);
136
- return timebuf;
137
- }
138
- /* Give years and months for 5 years or so */
139
- if (diff < 1825) {
140
- unsigned long years = (diff + 183) / 365;
141
- unsigned long months = (diff % 365 + 15) / 30;
142
- int n;
143
- n = snprintf(timebuf, sizeof(timebuf), "%lu year%s",
144
- years, (years > 1 ? "s" : ""));
145
- if (months)
146
- snprintf(timebuf + n, sizeof(timebuf) - n,
147
- ", %lu month%s ago",
148
- months, (months > 1 ? "s" : ""));
149
- else
150
- snprintf(timebuf + n, sizeof(timebuf) - n,
151
- " ago");
152
- return timebuf;
153
- }
154
- /* Otherwise, just years. Centuries is probably overkill. */
155
- snprintf(timebuf, sizeof(timebuf), "%lu years ago", (diff + 183) / 365);
156
- return timebuf;
163
+ return show_date_relative(time, tz, &now,
164
+ timebuf, sizeof(timebuf));
165
}
166
167
if (mode == DATE_LOCAL)
@@ -918,19 +926,13 @@ static void pending_number(struct tm *tm, int *num)
926
}
927
}
928
921
-unsigned long approxidate(const char *date)
929
+static unsigned long approxidate_str(const char *date, const struct timeval *tv)
930
{
931
int number = 0;
932
struct tm tm, now;
925
- struct timeval tv;
933
time_t time_sec;
927
- char buffer[50];
934
929
- if (parse_date(date, buffer, sizeof(buffer)) > 0)
930
- return strtoul(buffer, NULL, 10);
931
-
932
- gettimeofday(&tv, NULL);
933
- time_sec = tv.tv_sec;
935
+ time_sec = tv->tv_sec;
936
localtime_r(&time_sec, &tm);
937
now = tm;
938
@@ -954,3 +956,25 @@ unsigned long approxidate(const char *date)
956
pending_number(&tm, &number);
957
return update_tm(&tm, &now, 0);
958
}
959
+
960
+unsigned long approxidate_relative(const char *date, const struct timeval *tv)
961
+{
962
+ char buffer[50];
963
+
964
+ if (parse_date(date, buffer, sizeof(buffer)) > 0)
965
+ return strtoul(buffer, NULL, 0);
966
+
967
+ return approxidate_str(date, tv);
968
+}
969
+
970
+unsigned long approxidate(const char *date)
971
+{
972
+ struct timeval tv;
973
+ char buffer[50];
974
+
975
+ if (parse_date(date, buffer, sizeof(buffer)) > 0)
976
+ return strtoul(buffer, NULL, 0);
977
+
978
+ gettimeofday(&tv, NULL);
979
+ return approxidate_str(date, &tv);
980
+}