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