etc/services - sync with NetBSD-8
[minix.git] / crypto / external / bsd / heimdal / dist / lib / roken / strftime.c
blobc31658997a536365cc8c044430e1aba975acc5b5
1 /* $NetBSD: strftime.c,v 1.1.1.2 2014/04/24 12:45:52 pettai Exp $ */
3 /*
4 * Copyright (c) 1999 - 2002 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of KTH nor the names of its contributors may be
20 * used to endorse or promote products derived from this software without
21 * specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
35 #include <config.h>
36 #include <krb5/roken.h>
37 #ifdef TEST_STRPFTIME
38 #include "strpftime-test.h"
39 #endif
41 static const char *abb_weekdays[] = {
42 "Sun",
43 "Mon",
44 "Tue",
45 "Wed",
46 "Thu",
47 "Fri",
48 "Sat",
51 static const char *full_weekdays[] = {
52 "Sunday",
53 "Monday",
54 "Tuesday",
55 "Wednesday",
56 "Thursday",
57 "Friday",
58 "Saturday",
61 static const char *abb_month[] = {
62 "Jan",
63 "Feb",
64 "Mar",
65 "Apr",
66 "May",
67 "Jun",
68 "Jul",
69 "Aug",
70 "Sep",
71 "Oct",
72 "Nov",
73 "Dec"
76 static const char *full_month[] = {
77 "January",
78 "February",
79 "Mars",
80 "April",
81 "May",
82 "June",
83 "July",
84 "August",
85 "September",
86 "October",
87 "November",
88 "December"
91 static const char *ampm[] = {
92 "AM",
93 "PM"
97 * Convert hour in [0, 24] to [12 1 - 11 12 1 - 11 12]
100 static int
101 hour_24to12 (int hour)
103 int ret = hour % 12;
105 if (ret == 0)
106 ret = 12;
107 return ret;
111 * Return AM or PM for `hour'
114 static const char *
115 hour_to_ampm (int hour)
117 return ampm[hour / 12];
121 * Return the week number of `tm' (Sunday being the first day of the week)
122 * as [0, 53]
125 static int
126 week_number_sun (const struct tm *tm)
128 return (tm->tm_yday + 7 - (tm->tm_yday % 7 - tm->tm_wday + 7) % 7) / 7;
132 * Return the week number of `tm' (Monday being the first day of the week)
133 * as [0, 53]
136 static int
137 week_number_mon (const struct tm *tm)
139 int wday = (tm->tm_wday + 6) % 7;
141 return (tm->tm_yday + 7 - (tm->tm_yday % 7 - wday + 7) % 7) / 7;
145 * Return the week number of `tm' (Monday being the first day of the
146 * week) as [01, 53]. Week number one is the one that has four or more
147 * days in that year.
150 static int
151 week_number_mon4 (const struct tm *tm)
153 int wday = (tm->tm_wday + 6) % 7;
154 int w1day = (wday - tm->tm_yday % 7 + 7) % 7;
155 int ret;
157 ret = (tm->tm_yday + w1day) / 7;
158 if (w1day >= 4)
159 --ret;
160 if (ret == -1)
161 ret = 53;
162 else
163 ++ret;
164 return ret;
171 ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL
172 strftime (char *buf, size_t maxsize, const char *format,
173 const struct tm *tm)
175 size_t n = 0;
176 int ret;
178 while (*format != '\0' && n < maxsize) {
179 if (*format == '%') {
180 ++format;
181 if(*format == 'E' || *format == 'O')
182 ++format;
183 switch (*format) {
184 case 'a' :
185 ret = snprintf (buf, maxsize - n,
186 "%s", abb_weekdays[tm->tm_wday]);
187 break;
188 case 'A' :
189 ret = snprintf (buf, maxsize - n,
190 "%s", full_weekdays[tm->tm_wday]);
191 break;
192 case 'h' :
193 case 'b' :
194 ret = snprintf (buf, maxsize - n,
195 "%s", abb_month[tm->tm_mon]);
196 break;
197 case 'B' :
198 ret = snprintf (buf, maxsize - n,
199 "%s", full_month[tm->tm_mon]);
200 break;
201 case 'c' :
202 ret = snprintf (buf, maxsize - n,
203 "%d:%02d:%02d %02d:%02d:%02d",
204 tm->tm_year,
205 tm->tm_mon + 1,
206 tm->tm_mday,
207 tm->tm_hour,
208 tm->tm_min,
209 tm->tm_sec);
210 break;
211 case 'C' :
212 ret = snprintf (buf, maxsize - n,
213 "%02d", (tm->tm_year + 1900) / 100);
214 break;
215 case 'd' :
216 ret = snprintf (buf, maxsize - n,
217 "%02d", tm->tm_mday);
218 break;
219 case 'D' :
220 ret = snprintf (buf, maxsize - n,
221 "%02d/%02d/%02d",
222 tm->tm_mon + 1,
223 tm->tm_mday,
224 (tm->tm_year + 1900) % 100);
225 break;
226 case 'e' :
227 ret = snprintf (buf, maxsize - n,
228 "%2d", tm->tm_mday);
229 break;
230 case 'F':
231 ret = snprintf (buf, maxsize - n,
232 "%04d-%02d-%02d", tm->tm_year + 1900,
233 tm->tm_mon + 1, tm->tm_mday);
234 break;
235 case 'g':
236 /* last two digits of week-based year */
237 abort();
238 case 'G':
239 /* week-based year */
240 abort();
241 case 'H' :
242 ret = snprintf (buf, maxsize - n,
243 "%02d", tm->tm_hour);
244 break;
245 case 'I' :
246 ret = snprintf (buf, maxsize - n,
247 "%02d",
248 hour_24to12 (tm->tm_hour));
249 break;
250 case 'j' :
251 ret = snprintf (buf, maxsize - n,
252 "%03d", tm->tm_yday + 1);
253 break;
254 case 'k' :
255 ret = snprintf (buf, maxsize - n,
256 "%2d", tm->tm_hour);
257 break;
258 case 'l' :
259 ret = snprintf (buf, maxsize - n,
260 "%2d",
261 hour_24to12 (tm->tm_hour));
262 break;
263 case 'm' :
264 ret = snprintf (buf, maxsize - n,
265 "%02d", tm->tm_mon + 1);
266 break;
267 case 'M' :
268 ret = snprintf (buf, maxsize - n,
269 "%02d", tm->tm_min);
270 break;
271 case 'n' :
272 ret = snprintf (buf, maxsize - n, "\n");
273 break;
274 case 'p' :
275 ret = snprintf (buf, maxsize - n, "%s",
276 hour_to_ampm (tm->tm_hour));
277 break;
278 case 'r' :
279 ret = snprintf (buf, maxsize - n,
280 "%02d:%02d:%02d %s",
281 hour_24to12 (tm->tm_hour),
282 tm->tm_min,
283 tm->tm_sec,
284 hour_to_ampm (tm->tm_hour));
285 break;
286 case 'R' :
287 ret = snprintf (buf, maxsize - n,
288 "%02d:%02d",
289 tm->tm_hour,
290 tm->tm_min);
291 break;
292 case 's' :
293 ret = snprintf (buf, maxsize - n,
294 "%d", (int)mktime(rk_UNCONST(tm)));
295 break;
296 case 'S' :
297 ret = snprintf (buf, maxsize - n,
298 "%02d", tm->tm_sec);
299 break;
300 case 't' :
301 ret = snprintf (buf, maxsize - n, "\t");
302 break;
303 case 'T' :
304 case 'X' :
305 ret = snprintf (buf, maxsize - n,
306 "%02d:%02d:%02d",
307 tm->tm_hour,
308 tm->tm_min,
309 tm->tm_sec);
310 break;
311 case 'u' :
312 ret = snprintf (buf, maxsize - n,
313 "%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
314 break;
315 case 'U' :
316 ret = snprintf (buf, maxsize - n,
317 "%02d", week_number_sun (tm));
318 break;
319 case 'V' :
320 ret = snprintf (buf, maxsize - n,
321 "%02d", week_number_mon4 (tm));
322 break;
323 case 'w' :
324 ret = snprintf (buf, maxsize - n,
325 "%d", tm->tm_wday);
326 break;
327 case 'W' :
328 ret = snprintf (buf, maxsize - n,
329 "%02d", week_number_mon (tm));
330 break;
331 case 'x' :
332 ret = snprintf (buf, maxsize - n,
333 "%d:%02d:%02d",
334 tm->tm_year,
335 tm->tm_mon + 1,
336 tm->tm_mday);
337 break;
338 case 'y' :
339 ret = snprintf (buf, maxsize - n,
340 "%02d", (tm->tm_year + 1900) % 100);
341 break;
342 case 'Y' :
343 ret = snprintf (buf, maxsize - n,
344 "%d", tm->tm_year + 1900);
345 break;
346 case 'z':
347 ret = snprintf (buf, maxsize - n,
348 "%ld",
349 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
350 (long)tm->tm_gmtoff
351 #elif defined(HAVE_TIMEZONE)
352 #ifdef HAVE_ALTZONE
353 tm->tm_isdst ?
354 (long)altzone :
355 #endif
356 (long)timezone
357 #else
358 #error Where in timezone chaos are you?
359 #endif
361 break;
362 case 'Z' :
363 ret = snprintf (buf, maxsize - n,
364 "%s",
366 #if defined(HAVE_STRUCT_TM_TM_ZONE)
367 tm->tm_zone
368 #elif defined(HAVE_TIMEZONE)
369 tzname[tm->tm_isdst]
370 #else
371 #error what?
372 #endif
374 break;
375 case '\0' :
376 --format;
377 /* FALLTHROUGH */
378 case '%' :
379 ret = snprintf (buf, maxsize - n,
380 "%%");
381 break;
382 default :
383 ret = snprintf (buf, maxsize - n,
384 "%%%c", *format);
385 break;
387 if (ret < 0 || ret >= (int)(maxsize - n))
388 return 0;
389 n += ret;
390 buf += ret;
391 ++format;
392 } else {
393 *buf++ = *format++;
394 ++n;
397 *buf = '\0';
398 return n;