@@ -86,6 +86,67 @@ static int local_tzoffset(unsigned long time)
8686 return offset * eastwest ;
8787}
8888
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+
89150const char * show_date (unsigned long time , int tz , enum date_mode mode )
90151{
91152 struct tm * tm ;
@@ -97,63 +158,10 @@ const char *show_date(unsigned long time, int tz, enum date_mode mode)
97158 }
98159
99160 if (mode == DATE_RELATIVE ) {
100- unsigned long diff ;
101161 struct timeval now ;
102162 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 ));
157165 }
158166
159167 if (mode == DATE_LOCAL )
@@ -918,19 +926,13 @@ static void pending_number(struct tm *tm, int *num)
918926 }
919927}
920928
921- unsigned long approxidate (const char * date )
929+ static unsigned long approxidate_str (const char * date , const struct timeval * tv )
922930{
923931 int number = 0 ;
924932 struct tm tm , now ;
925- struct timeval tv ;
926933 time_t time_sec ;
927- char buffer [50 ];
928934
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 ;
934936 localtime_r (& time_sec , & tm );
935937 now = tm ;
936938
@@ -954,3 +956,25 @@ unsigned long approxidate(const char *date)
954956 pending_number (& tm , & number );
955957 return update_tm (& tm , & now , 0 );
956958}
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+ }
0 commit comments