Removed monthname() and replaced with proper strftime() calls.
[citadel.git] / webcit / fmt_date.c
1 /*
2  * $Id$
3  */
4 /**
5  * \defgroup FormatDates Miscellaneous routines formating dates
6  * \ingroup Calendaring
7  */
8 /*@{*/
9 #include "webcit.h"
10 #include "webserver.h"
11
12 typedef unsigned char byte; /**< a byte. */
13
14 #define FALSE 0 /**< no. */
15 #define TRUE 1 /**< yes. */
16
17 /**
18  * \brief       Wrapper around strftime() or strftime_l()
19  *              depending upon how our build is configured.
20  *
21  * \param       s       String target buffer
22  * \param       max     Maximum size of string target buffer
23  * \param       format  strftime() format
24  * \param       tm      Input date/time
25  */
26 size_t wc_strftime(char *s, size_t max, const char *format, const struct tm *tm)
27 {
28 #ifdef ENABLE_NLS
29         return strftime_l(s, max, format, tm, wc_locales[WC->selected_language]);
30 #else
31         return strftime(s, max, format, tm);
32 #endif
33 }
34
35
36 /**
37  * \brief Format a date/time stamp for output 
38  * \param buf the output buffer
39  * \param thetime time to convert to string 
40  * \param brief do we want compact view?????
41  */
42 void fmt_date(char *buf, time_t thetime, int brief)
43 {
44         struct tm tm;
45         struct tm today_tm;
46         time_t today_timet;
47         int hour;
48         char calhourformat[16];
49
50         get_preference("calhourformat", calhourformat, sizeof calhourformat);
51
52         today_timet = time(NULL);
53         localtime_r(&today_timet, &today_tm);
54
55         localtime_r(&thetime, &tm);
56         hour = tm.tm_hour;
57         if (hour == 0)
58                 hour = 12;
59         else if (hour > 12)
60                 hour = hour - 12;
61
62         buf[0] = 0;
63
64         if (brief) {
65
66                 /** If date == today, show only the time */
67                 if ((tm.tm_year == today_tm.tm_year)
68                   &&(tm.tm_mon == today_tm.tm_mon)
69                   &&(tm.tm_mday == today_tm.tm_mday)) {
70                         wc_strftime(buf, 32, "%l:%M%p", &tm);
71                 }
72                 /** Otherwise, for messages up to 6 months old, show the
73                  * month and day, and the time */
74                 else if (today_timet - thetime < 15552000) {
75                         wc_strftime(buf, 32, "%b %d %l:%M%p", &tm);
76                 }
77                 /** older than 6 months, show only the date */
78                 else {
79                         wc_strftime(buf, 32, "%b %d %Y", &tm);
80                 }
81         }
82         else {
83                 wc_strftime(buf, 32, "%c", &tm);
84         }
85 }
86
87
88 /**
89  * \brief Format TIME ONLY for output 
90  * \param buf the output buffer
91  * \param thetime time to format into buf
92  */
93 void fmt_time(char *buf, time_t thetime)
94 {
95         struct tm *tm;
96         int hour;
97         char calhourformat[16];
98
99         get_preference("calhourformat", calhourformat, sizeof calhourformat);
100
101         buf[0] = 0;
102         tm = localtime(&thetime);
103         hour = tm->tm_hour;
104         if (hour == 0)
105                 hour = 12;
106         else if (hour > 12)
107                 hour = hour - 12;
108
109         if (!strcasecmp(calhourformat, "24")) {
110                 sprintf(buf, "%2d:%02d",
111                         tm->tm_hour, tm->tm_min
112                 );
113         }
114         else {
115                 sprintf(buf, "%d:%02d%s",
116                         hour, tm->tm_min, ((tm->tm_hour > 12) ? "pm" : "am")
117                 );
118         }
119 }
120
121
122
123
124 /**
125  * \brief Break down the timestamp used in HTTP headers
126  * Should read rfc1123 and rfc850 dates OK
127  * \todo FIXME won't read asctime
128  * Doesn't understand timezone, but we only should be using GMT/UTC anyway
129  * \param buf time to parse
130  * \return the time found in buf
131  */
132 time_t httpdate_to_timestamp(char *buf)
133 {
134         time_t t = 0;
135         struct tm tt;
136         char *c;
137         char tz[256];
138
139         /** Skip day of week, to number */
140         for (c = buf; *c != ' '; c++)
141                 ;
142         c++;
143
144         /* Get day of month */
145         tt.tm_mday = atoi(c);
146         for (; *c != ' ' && *c != '-'; c++);
147         c++;
148
149         /** Get month */
150         switch (*c) {
151         case 'A':       /** April, August */
152                 tt.tm_mon = (c[1] == 'p') ? 3 : 7;
153                 break;
154         case 'D':       /** December */
155                 tt.tm_mon = 11;
156                 break;
157         case 'F':       /** February */
158                 tt.tm_mon = 1;
159                 break;
160         case 'M':       /** March, May */
161                 tt.tm_mon = (c[2] == 'r') ? 2 : 4;
162                 break;
163         case 'J':       /** January, June, July */
164                 tt.tm_mon = (c[2] == 'n') ? ((c[1] == 'a') ? 0 : 5) : 6;
165                 break;
166         case 'N':       /** November */
167                 tt.tm_mon = 10;
168                 break;
169         case 'O':       /** October */
170                 tt.tm_mon = 9;
171                 break;
172         case 'S':       /** September */
173                 tt.tm_mon = 8;
174                 break;
175         default:
176                 return 42;
177                 break;  /** NOTREACHED */
178         }
179         c += 4;
180
181         tt.tm_year = 0;
182         /** Get year */
183         tt.tm_year = atoi(c);
184         for (; *c != ' '; c++);
185         c++;
186         if (tt.tm_year >= 1900)
187                 tt.tm_year -= 1900;
188
189         /** Get hour */
190         tt.tm_hour = atoi(c);
191         for (; *c != ':'; c++);
192         c++;
193
194         /** Get minute */
195         tt.tm_min = atoi(c);
196         for (; *c != ':'; c++);
197         c++;
198
199         /** Get second */
200         tt.tm_sec = atoi(c);
201         for (; *c && *c != ' '; c++);
202
203         /** Got everything; let's go */
204         /** First, change to UTC */
205         if (getenv("TZ"))
206                 sprintf(tz, "TZ=%s", getenv("TZ"));
207         else
208                 strcpy(tz, "TZ=");
209         putenv("TZ=UTC");
210         tzset();
211         t = mktime(&tt);
212         putenv(tz);
213         tzset();
214         return t;
215 }
216
217
218
219
220 /*@}*/