]>
git.saurik.com Git - apple/libc.git/blob - stdtime/FreeBSD/strftime.c
565c6d1c8ef1dcb5dc1d34dd828c75a30cc76651
2 * Copyright (c) 1989 The Regents of the University of California.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 static const char elsieid
[] = "@(#)strftime.c 7.38";
22 ** Based on the UCB version with the ID appearing below.
23 ** This is ANSIish only when "multibyte character == plain character".
25 #endif /* !defined NOID */
26 #endif /* !defined lint */
28 #include "namespace.h"
31 #if defined(LIBC_SCCS) && !defined(lint)
32 static const char sccsid
[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
33 #endif /* LIBC_SCCS and not lint */
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD: src/lib/libc/stdtime/strftime.c,v 1.38 2002/09/06 11:24:03 tjr Exp $");
40 #include "un-namespace.h"
41 #include "timelocal.h"
43 static char * _add(const char *, char *, const char *);
44 static char * _conv(int, const char *, char *, const char *);
45 static char * _fmt(const char *, const struct tm
*, char *, const char *);
47 size_t strftime(char * __restrict
, size_t, const char * __restrict
,
48 const struct tm
* __restrict
);
50 extern char * tzname
[];
53 strftime(char * __restrict s
, size_t maxsize
, const char * __restrict format
,
54 const struct tm
* __restrict t
)
59 p
= _fmt(((format
== NULL
) ? "%c" : format
), t
, s
, s
+ maxsize
);
67 _fmt(format
, t
, pt
, ptlim
)
69 const struct tm
*const t
;
71 const char *const ptlim
;
73 int Ealternative
, Oalternative
;
74 struct lc_time_T
*tptr
= __get_current_time_locale();
76 for ( ; *format
; ++format
) {
86 pt
= _add((t
->tm_wday
< 0 || t
->tm_wday
> 6) ?
87 "?" : tptr
->weekday
[t
->tm_wday
],
91 pt
= _add((t
->tm_wday
< 0 || t
->tm_wday
> 6) ?
92 "?" : tptr
->wday
[t
->tm_wday
],
96 pt
= _add((t
->tm_mon
< 0 || t
->tm_mon
> 11) ?
97 "?" : (Oalternative
? tptr
->alt_month
:
98 tptr
->month
)[t
->tm_mon
],
103 pt
= _add((t
->tm_mon
< 0 || t
->tm_mon
> 11) ?
104 "?" : tptr
->mon
[t
->tm_mon
],
109 ** %C used to do a...
110 ** _fmt("%a %b %e %X %Y", t);
111 ** ...whereas now POSIX 1003.2 calls for
112 ** something completely different.
115 pt
= _conv((t
->tm_year
+ TM_YEAR_BASE
) / 100,
119 pt
= _fmt(tptr
->c_fmt
, t
, pt
, ptlim
);
122 pt
= _fmt("%m/%d/%y", t
, pt
, ptlim
);
125 pt
= _conv(t
->tm_mday
, "%02d", pt
, ptlim
);
128 if (Ealternative
|| Oalternative
)
134 ** POSIX locale extensions, a la
135 ** Arnold Robbins' strftime version 3.0.
137 ** %Ec %EC %Ex %EX %Ey %EY
138 ** %Od %oe %OH %OI %Om %OM
139 ** %OS %Ou %OU %OV %Ow %OW %Oy
140 ** are supposed to provide alternate
144 ** FreeBSD extensions
147 if (Ealternative
|| Oalternative
)
152 pt
= _conv(t
->tm_mday
, "%2d", pt
, ptlim
);
155 pt
= _fmt("%Y-%m-%d", t
, pt
, ptlim
);
158 pt
= _conv(t
->tm_hour
, "%02d", pt
, ptlim
);
161 pt
= _conv((t
->tm_hour
% 12) ?
162 (t
->tm_hour
% 12) : 12,
166 pt
= _conv(t
->tm_yday
+ 1, "%03d", pt
, ptlim
);
170 ** This used to be...
171 ** _conv(t->tm_hour % 12 ?
172 ** t->tm_hour % 12 : 12, 2, ' ');
173 ** ...and has been changed to the below to
174 ** match SunOS 4.1.1 and Arnold Robbins'
175 ** strftime version 3.0. That is, "%k" and
176 ** "%l" have been swapped.
179 pt
= _conv(t
->tm_hour
, "%2d", pt
, ptlim
);
184 ** After all this time, still unclaimed!
186 pt
= _add("kitchen sink", pt
, ptlim
);
188 #endif /* defined KITCHEN_SINK */
191 ** This used to be...
192 ** _conv(t->tm_hour, 2, ' ');
193 ** ...and has been changed to the below to
194 ** match SunOS 4.1.1 and Arnold Robbin's
195 ** strftime version 3.0. That is, "%k" and
196 ** "%l" have been swapped.
199 pt
= _conv((t
->tm_hour
% 12) ?
200 (t
->tm_hour
% 12) : 12,
204 pt
= _conv(t
->tm_min
, "%02d", pt
, ptlim
);
207 pt
= _conv(t
->tm_mon
+ 1, "%02d", pt
, ptlim
);
210 pt
= _add("\n", pt
, ptlim
);
213 pt
= _add((t
->tm_hour
>= 12) ?
219 pt
= _fmt("%H:%M", t
, pt
, ptlim
);
222 pt
= _fmt(tptr
->ampm_fmt
, t
, pt
, ptlim
);
225 pt
= _conv(t
->tm_sec
, "%02d", pt
, ptlim
);
230 char buf
[INT_STRLEN_MAXIMUM(
236 if (TYPE_SIGNED(time_t))
237 (void) sprintf(buf
, "%ld",
239 else (void) sprintf(buf
, "%lu",
240 (unsigned long) mkt
);
241 pt
= _add(buf
, pt
, ptlim
);
245 pt
= _fmt("%H:%M:%S", t
, pt
, ptlim
);
248 pt
= _add("\t", pt
, ptlim
);
251 pt
= _conv((t
->tm_yday
+ 7 - t
->tm_wday
) / 7,
256 ** From Arnold Robbins' strftime version 3.0:
257 ** "ISO 8601: Weekday as a decimal number
261 pt
= _conv((t
->tm_wday
== 0) ? 7 : t
->tm_wday
,
264 case 'V': /* ISO 8601 week number */
265 case 'G': /* ISO 8601 year (four digits) */
266 case 'g': /* ISO 8601 year (two digits) */
268 ** From Arnold Robbins' strftime version 3.0: "the week number of the
269 ** year (the first Monday as the first day of week 1) as a decimal number
273 ** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
274 ** "Week 01 of a year is per definition the first week which has the
275 ** Thursday in this year, which is equivalent to the week which contains
276 ** the fourth day of January. In other words, the first week of a new year
277 ** is the week which has the majority of its days in the new year. Week 01
278 ** might also contain days from the previous year and the week before week
279 ** 01 of a year is the last week (52 or 53) of the previous year even if
280 ** it contains days from the new year. A week starts with Monday (day 1)
281 ** and ends with Sunday (day 7). For example, the first week of the year
282 ** 1997 lasts from 1996-12-30 to 1997-01-05..."
291 year
= t
->tm_year
+ TM_YEAR_BASE
;
303 ** What yday (-3 ... 3) does
304 ** the ISO year begin on?
306 bot
= ((yday
+ 11 - wday
) %
309 ** What yday does the NEXT
310 ** ISO year begin on?
323 w
= 1 + ((yday
- bot
) /
328 yday
+= isleap(year
) ?
332 #ifdef XPG4_1994_04_09
334 && t
->tm_mon
== TM_JANUARY
)
336 && t
->tm_mon
== TM_DECEMBER
))
338 #endif /* defined XPG4_1994_04_09 */
340 pt
= _conv(w
, "%02d",
342 else if (*format
== 'g') {
343 pt
= _conv(year
% 100, "%02d",
345 } else pt
= _conv(year
, "%04d",
351 ** From Arnold Robbins' strftime version 3.0:
352 ** "date as dd-bbb-YYYY"
355 pt
= _fmt("%e-%b-%Y", t
, pt
, ptlim
);
358 pt
= _conv((t
->tm_yday
+ 7 -
360 (t
->tm_wday
- 1) : 6)) / 7,
364 pt
= _conv(t
->tm_wday
, "%d", pt
, ptlim
);
367 pt
= _fmt(tptr
->X_fmt
, t
, pt
, ptlim
);
370 pt
= _fmt(tptr
->x_fmt
, t
, pt
, ptlim
);
373 pt
= _conv((t
->tm_year
+ TM_YEAR_BASE
) % 100,
377 pt
= _conv(t
->tm_year
+ TM_YEAR_BASE
, "%04d",
381 if (t
->tm_zone
!= NULL
)
382 pt
= _add(t
->tm_zone
, pt
, ptlim
);
384 if (t
->tm_isdst
== 0 || t
->tm_isdst
== 1) {
385 pt
= _add(tzname
[t
->tm_isdst
],
387 } else pt
= _add("?", pt
, ptlim
);
392 if (t
->tm_gmtoff
>= 0) {
393 absoff
= t
->tm_gmtoff
;
394 pt
= _add("+", pt
, ptlim
);
396 absoff
= -t
->tm_gmtoff
;
397 pt
= _add("-", pt
, ptlim
);
399 pt
= _conv(absoff
/ 3600, "%02d",
401 pt
= _conv((absoff
% 3600) / 60, "%02d",
406 pt
= _fmt(tptr
->date_fmt
, t
, pt
, ptlim
);
410 * X311J/88-090 (4.12.3.5): if conversion char is
411 * undefined, behavior is undefined. Print out the
412 * character itself as printf(3) also does.
426 _conv(n
, format
, pt
, ptlim
)
428 const char *const format
;
430 const char *const ptlim
;
432 char buf
[INT_STRLEN_MAXIMUM(int) + 1];
434 (void) sprintf(buf
, format
, n
);
435 return _add(buf
, pt
, ptlim
);
442 const char *const ptlim
;
444 while (pt
< ptlim
&& (*pt
= *str
++) != '\0')