* fmt_date.c: changes to "brief" mode. It now displays time only if the
[citadel.git] / webcit / fmt_date.c
1 /*
2  * $Id$
3  *
4  * Miscellaneous routines 
5  */
6
7 #include "webcit.h"
8 #include "webserver.h"
9
10 typedef unsigned char byte;
11
12 #define FALSE 0
13 #define TRUE 1
14
15 char *ascmonths[] = {
16         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
17         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
18 };
19
20 char *ascdays[] = {
21         "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
22 };
23
24 /*
25  * Format a date/time stamp for output 
26  */
27 void fmt_date(char *buf, time_t thetime, int brief)
28 {
29         struct tm tm;
30         struct tm today_tm;
31         time_t today_timet;
32         int hour;
33         char calhourformat[16];
34
35         get_preference("calhourformat", calhourformat, sizeof calhourformat);
36
37         today_timet = time(NULL);
38         localtime_r(&today_timet, &today_tm);
39
40         localtime_r(&thetime, &tm);
41         hour = tm.tm_hour;
42         if (hour == 0)
43                 hour = 12;
44         else if (hour > 12)
45                 hour = hour - 12;
46
47         buf[0] = 0;
48
49         if (brief) {
50
51                 /* If date == today, show only the time */
52                 if ((tm.tm_year == today_tm.tm_year)
53                   &&(tm.tm_mon == today_tm.tm_mon)
54                   &&(tm.tm_mday == today_tm.tm_mday)) {
55                         if (!strcasecmp(calhourformat, "24")) {
56                                 sprintf(buf, "%2d:%02d",
57                                         tm.tm_hour, tm.tm_min
58                                 );
59                         }
60                         else {
61                                 sprintf(buf, "%2d:%02d%s",
62                                         hour, tm.tm_min,
63                                         ((tm.tm_hour >= 12) ? "pm" : "am")
64                                 );
65                         }
66                 }
67
68                 /* Otherwise, for messages up to 6 months old, show the
69                  * month and day, and the time */
70                 else if (today_timet - thetime < 15552000) {
71                         if (!strcasecmp(calhourformat, "24")) {
72                                 sprintf(buf, "%s %d %2d:%02d",
73                                         ascmonths[tm.tm_mon],
74                                         tm.tm_mday,
75                                         tm.tm_hour, tm.tm_min
76                                 );
77                         }
78                         else {
79                                 sprintf(buf, "%s %d %2d:%02d%s",
80                                         ascmonths[tm.tm_mon],
81                                         tm.tm_mday,
82                                         hour, tm.tm_min,
83                                         ((tm.tm_hour >= 12) ? "pm" : "am")
84                                 );
85                         }
86                 }
87
88                 /* older than 6 months, show only the date */
89                 else {
90                         sprintf(buf, "%s %d %d",
91                                 ascmonths[tm.tm_mon],
92                                 tm.tm_mday,
93                                 tm.tm_year + 1900
94                         );
95                 }
96         }
97         else {
98                 if (!strcasecmp(calhourformat, "24")) {
99                         sprintf(buf, "%s %d %d %2d:%02d",
100                                 ascmonths[tm.tm_mon],
101                                 tm.tm_mday,
102                                 tm.tm_year + 1900,
103                                 tm.tm_hour, tm.tm_min
104                         );
105                 }
106                 else {
107                         sprintf(buf, "%s %d %d %2d:%02d%s",
108                                 ascmonths[tm.tm_mon],
109                                 tm.tm_mday,
110                                 tm.tm_year + 1900,
111                                 hour, tm.tm_min, ((tm.tm_hour >= 12) ? "pm" : "am")
112                         );
113                 }
114         }
115 }
116
117
118
119 /*
120  * Format TIME ONLY for output 
121  */
122 void fmt_time(char *buf, time_t thetime)
123 {
124         struct tm *tm;
125         int hour;
126         char calhourformat[16];
127
128         get_preference("calhourformat", calhourformat, sizeof calhourformat);
129
130         buf[0] = 0;
131         tm = localtime(&thetime);
132         hour = tm->tm_hour;
133         if (hour == 0)
134                 hour = 12;
135         else if (hour > 12)
136                 hour = hour - 12;
137
138         if (!strcasecmp(calhourformat, "24")) {
139                 sprintf(buf, "%2d:%02d",
140                         tm->tm_hour, tm->tm_min
141                 );
142         }
143         else {
144                 sprintf(buf, "%d:%02d%s",
145                         hour, tm->tm_min, ((tm->tm_hour > 12) ? "pm" : "am")
146                 );
147         }
148 }
149
150
151
152
153 /*
154  * Format a date/time stamp to the format used in HTTP headers
155  */
156 void httpdate(char *buf, time_t thetime)
157 {
158         struct tm *tm;
159
160         buf[0] = 0;
161         tm = localtime(&thetime);
162
163         sprintf(buf, "%s, %02d %s %4d %02d:%02d:%02d",
164                 ascdays[tm->tm_wday],
165                 tm->tm_mday,
166                 ascmonths[tm->tm_mon],
167                 tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec);
168 }
169
170
171 /*
172  * Break down the timestamp used in HTTP headers
173  * Should read rfc1123 and rfc850 dates OK
174  * FIXME won't read asctime
175  * Doesn't understand timezone, but we only should be using GMT/UTC anyway
176  */
177 time_t httpdate_to_timestamp(const char *buf)
178 {
179         time_t t = 0;
180         struct tm tt;
181         char *c;
182         char tz[256];
183
184         /* Skip day of week, to number */
185         for (c = buf; *c != ' '; c++)
186                 ;
187         c++;
188
189         /* Get day of month */
190         tt.tm_mday = atoi(c);
191         for (; *c != ' ' && *c != '-'; c++);
192         c++;
193
194         /* Get month */
195         switch (*c) {
196         case 'A':       /* April, August */
197                 tt.tm_mon = (c[1] == 'p') ? 3 : 7;
198                 break;
199         case 'D':       /* December */
200                 tt.tm_mon = 11;
201                 break;
202         case 'F':       /* February */
203                 tt.tm_mon = 1;
204                 break;
205         case 'M':       /* March, May */
206                 tt.tm_mon = (c[2] == 'r') ? 2 : 4;
207                 break;
208         case 'J':       /* January, June, July */
209                 tt.tm_mon = (c[2] == 'n') ? ((c[1] == 'a') ? 0 : 5) : 6;
210                 break;
211         case 'N':       /* November */
212                 tt.tm_mon = 10;
213                 break;
214         case 'O':       /* October */
215                 tt.tm_mon = 9;
216                 break;
217         case 'S':       /* September */
218                 tt.tm_mon = 8;
219                 break;
220         default:
221                 return 42;
222                 break;  /* NOTREACHED */
223         }
224         c += 4;
225
226         tt.tm_year = 0;
227         /* Get year */
228         tt.tm_year = atoi(c);
229         for (; *c != ' '; c++);
230         c++;
231         if (tt.tm_year >= 1900)
232                 tt.tm_year -= 1900;
233
234         /* Get hour */
235         tt.tm_hour = atoi(c);
236         for (; *c != ':'; c++);
237         c++;
238
239         /* Get minute */
240         tt.tm_min = atoi(c);
241         for (; *c != ':'; c++);
242         c++;
243
244         /* Get second */
245         tt.tm_sec = atoi(c);
246         for (; *c && *c != ' '; c++);
247
248         /* Got everything; let's go */
249         /* First, change to UTC */
250         if (getenv("TZ"))
251                 sprintf(tz, "TZ=%s", getenv("TZ"));
252         else
253                 strcpy(tz, "TZ=");
254         putenv("TZ=UTC");
255         tzset();
256         t = mktime(&tt);
257         putenv(tz);
258         tzset();
259         return t;
260 }