@matheusbsbs / matheus-bagliano / commits / 33012fc429
Fork 0

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 +}