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