exp2l: Work around a NetBSD 10.0/i386 bug.
[gnulib.git] / lib / strftime.c
blob684d910771f758b63c265d6cfca5a5d0bdcaf080
1 /* Copyright (C) 1991-2024 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation, either version 3 of the
7 License, or (at your option) any later version.
9 This file is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 #ifndef FPRINTFTIME
18 # define FPRINTFTIME 0
19 #endif
21 #ifndef USE_C_LOCALE
22 # define USE_C_LOCALE 0
23 #endif
25 #ifdef _LIBC
26 # define USE_IN_EXTENDED_LOCALE_MODEL 1
27 # define HAVE_STRUCT_ERA_ENTRY 1
28 # define HAVE_TM_GMTOFF 1
29 # define HAVE_STRUCT_TM_TM_ZONE 1
30 # define HAVE_TZNAME 1
31 # include "../locale/localeinfo.h"
32 #else
33 # include <libc-config.h>
34 # if FPRINTFTIME
35 # include "fprintftime.h"
36 # else
37 # include "strftime.h"
38 # endif
39 # include "time-internal.h"
40 #endif
42 /* Whether to require GNU behavior for AM and PM indicators, even on
43 other platforms. This matters only in non-C locales.
44 The default is to require it; you can override this via
45 AC_DEFINE([REQUIRE_GNUISH_STRFTIME_AM_PM], 1) and if you do that
46 you may be able to omit Gnulib's localename module and its dependencies. */
47 #ifndef REQUIRE_GNUISH_STRFTIME_AM_PM
48 # define REQUIRE_GNUISH_STRFTIME_AM_PM true
49 #endif
50 #if USE_C_LOCALE
51 # undef REQUIRE_GNUISH_STRFTIME_AM_PM
52 # define REQUIRE_GNUISH_STRFTIME_AM_PM false
53 #endif
55 #if USE_C_LOCALE
56 # include "c-ctype.h"
57 #else
58 # include <ctype.h>
59 #endif
60 #include <errno.h>
61 #include <time.h>
63 #if HAVE_TZNAME && !HAVE_DECL_TZNAME
64 extern char *tzname[];
65 #endif
67 /* Do multibyte processing if multibyte encodings are supported, unless
68 multibyte sequences are safe in formats. Multibyte sequences are
69 safe if they cannot contain byte sequences that look like format
70 conversion specifications. The multibyte encodings used by the
71 C library on the various platforms (UTF-8, GB2312, GBK, CP936,
72 GB18030, EUC-TW, BIG5, BIG5-HKSCS, CP950, EUC-JP, EUC-KR, CP949,
73 SHIFT_JIS, CP932, JOHAB) are safe for formats, because the byte '%'
74 cannot occur in a multibyte character except in the first byte.
76 The DEC-HANYU encoding used on OSF/1 is not safe for formats, but
77 this encoding has never been seen in real-life use, so we ignore
78 it. */
79 #if !(defined __osf__ && 0)
80 # define MULTIBYTE_IS_FORMAT_SAFE 1
81 #endif
82 #define DO_MULTIBYTE (! MULTIBYTE_IS_FORMAT_SAFE)
84 #if DO_MULTIBYTE
85 # include <wchar.h>
86 static const mbstate_t mbstate_zero;
87 #endif
89 #include <limits.h>
90 #include <stdckdint.h>
91 #include <stddef.h>
92 #include <stdlib.h>
93 #include <string.h>
95 #if USE_C_LOCALE && HAVE_STRFTIME_L
96 # include <locale.h>
97 #endif
99 #if (defined __NetBSD__ || defined __sun) && REQUIRE_GNUISH_STRFTIME_AM_PM
100 # include <locale.h>
101 # include "localename.h"
102 #endif
104 #include "attribute.h"
105 #include <intprops.h>
107 #ifdef COMPILE_WIDE
108 # include <endian.h>
109 # define CHAR_T wchar_t
110 # define UCHAR_T unsigned int
111 # define L_(Str) L##Str
112 # define NLW(Sym) _NL_W##Sym
114 # define MEMCPY(d, s, n) __wmemcpy (d, s, n)
115 # define STRLEN(s) __wcslen (s)
117 #else
118 # define CHAR_T char
119 # define UCHAR_T unsigned char
120 # define L_(Str) Str
121 # define NLW(Sym) Sym
122 # define ABALTMON_1 _NL_ABALTMON_1
124 # define MEMCPY(d, s, n) memcpy (d, s, n)
125 # define STRLEN(s) strlen (s)
127 #endif
129 /* Shift A right by B bits portably, by dividing A by 2**B and
130 truncating towards minus infinity. A and B should be free of side
131 effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
132 INT_BITS is the number of useful bits in an int. GNU code can
133 assume that INT_BITS is at least 32.
135 ISO C99 says that A >> B is implementation-defined if A < 0. Some
136 implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
137 right in the usual way when A < 0, so SHR falls back on division if
138 ordinary A >> B doesn't seem to be the usual signed shift. */
139 #define SHR(a, b) \
140 (-1 >> 1 == -1 \
141 ? (a) >> (b) \
142 : ((a) + ((a) < 0)) / (1 << (b)) - ((a) < 0))
144 #define TM_YEAR_BASE 1900
146 #ifndef __isleap
147 /* Nonzero if YEAR is a leap year (every 4 years,
148 except every 100th isn't, and every 400th is). */
149 # define __isleap(year) \
150 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
151 #endif
154 #ifdef _LIBC
155 # define mktime_z(tz, tm) mktime (tm)
156 # define tzname __tzname
157 # define tzset __tzset
159 # define time_t __time64_t
160 # define __gmtime_r(t, tp) __gmtime64_r (t, tp)
161 # define mktime(tp) __mktime64 (tp)
162 #endif
164 #if FPRINTFTIME
165 # define STREAM_OR_CHAR_T FILE
166 # define STRFTIME_ARG(x) /* empty */
167 #else
168 # define STREAM_OR_CHAR_T CHAR_T
169 # define STRFTIME_ARG(x) x,
170 #endif
172 #if FPRINTFTIME
173 # define memset_byte(P, Len, Byte) \
174 do { size_t _i; for (_i = 0; _i < Len; _i++) fputc (Byte, P); } while (0)
175 # define memset_space(P, Len) memset_byte (P, Len, ' ')
176 # define memset_zero(P, Len) memset_byte (P, Len, '0')
177 #elif defined COMPILE_WIDE
178 # define memset_space(P, Len) (wmemset (P, L' ', Len), (P) += (Len))
179 # define memset_zero(P, Len) (wmemset (P, L'0', Len), (P) += (Len))
180 #else
181 # define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len))
182 # define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len))
183 #endif
185 #if FPRINTFTIME
186 # define advance(P, N)
187 #else
188 # define advance(P, N) ((P) += (N))
189 #endif
191 #define add(n, f) width_add (width, n, f)
192 #define width_add(width, n, f) \
193 do \
195 size_t _n = (n); \
196 size_t _w = pad == L_('-') || width < 0 ? 0 : width; \
197 size_t _incr = _n < _w ? _w : _n; \
198 if (_incr >= maxsize - i) \
200 errno = ERANGE; \
201 return 0; \
203 if (p) \
205 if (_n < _w) \
207 size_t _delta = _w - _n; \
208 if (pad == L_('0') || pad == L_('+')) \
209 memset_zero (p, _delta); \
210 else \
211 memset_space (p, _delta); \
213 f; \
214 advance (p, _n); \
216 i += _incr; \
217 } while (0)
219 #define add1(c) width_add1 (width, c)
220 #if FPRINTFTIME
221 # define width_add1(width, c) width_add (width, 1, fputc (c, p))
222 #else
223 # define width_add1(width, c) width_add (width, 1, *p = c)
224 #endif
226 #define cpy(n, s) width_cpy (width, n, s)
227 #if FPRINTFTIME
228 # define width_cpy(width, n, s) \
229 width_add (width, n, \
230 do \
232 if (to_lowcase) \
233 fwrite_lowcase (p, (s), _n); \
234 else if (to_uppcase) \
235 fwrite_uppcase (p, (s), _n); \
236 else \
238 /* Ignore the value of fwrite. The caller can determine whether \
239 an error occurred by inspecting ferror (P). All known fwrite \
240 implementations set the stream's error indicator when they \
241 fail due to ENOMEM etc., even though C11 and POSIX.1-2008 do \
242 not require this. */ \
243 fwrite (s, _n, 1, p); \
246 while (0) \
248 #else
249 # define width_cpy(width, n, s) \
250 width_add (width, n, \
251 if (to_lowcase) \
252 memcpy_lowcase (p, (s), _n LOCALE_ARG); \
253 else if (to_uppcase) \
254 memcpy_uppcase (p, (s), _n LOCALE_ARG); \
255 else \
256 MEMCPY ((void *) p, (void const *) (s), _n))
257 #endif
259 #ifdef COMPILE_WIDE
260 # ifndef USE_IN_EXTENDED_LOCALE_MODEL
261 # undef __mbsrtowcs_l
262 # define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
263 # endif
264 #endif
267 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
268 /* We use this code also for the extended locale handling where the
269 function gets as an additional argument the locale which has to be
270 used. To access the values we have to redefine the _NL_CURRENT
271 macro. */
272 # define strftime __strftime_l
273 # define wcsftime __wcsftime_l
274 # undef _NL_CURRENT
275 # define _NL_CURRENT(category, item) \
276 (current->values[_NL_ITEM_INDEX (item)].string)
277 # define LOCALE_PARAM , locale_t loc
278 # define LOCALE_ARG , loc
279 # define HELPER_LOCALE_ARG , current
280 #else
281 # define LOCALE_PARAM
282 # define LOCALE_ARG
283 # ifdef _LIBC
284 # define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
285 # else
286 # define HELPER_LOCALE_ARG
287 # endif
288 #endif
290 #ifdef COMPILE_WIDE
291 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
292 # define TOUPPER(Ch, L) __towupper_l (Ch, L)
293 # define TOLOWER(Ch, L) __towlower_l (Ch, L)
294 # else
295 # define TOUPPER(Ch, L) towupper (Ch)
296 # define TOLOWER(Ch, L) towlower (Ch)
297 # endif
298 #else
299 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
300 # define TOUPPER(Ch, L) __toupper_l (Ch, L)
301 # define TOLOWER(Ch, L) __tolower_l (Ch, L)
302 # else
303 # if USE_C_LOCALE
304 # define TOUPPER(Ch, L) c_toupper (Ch)
305 # define TOLOWER(Ch, L) c_tolower (Ch)
306 # else
307 # define TOUPPER(Ch, L) toupper (Ch)
308 # define TOLOWER(Ch, L) tolower (Ch)
309 # endif
310 # endif
311 #endif
312 /* We don't use 'isdigit' here since the locale dependent
313 interpretation is not what we want here. We only need to accept
314 the arabic digits in the ASCII range. One day there is perhaps a
315 more reliable way to accept other sets of digits. */
316 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
318 /* Avoid false GCC warning "'memset' specified size 18446744073709551615 exceeds
319 maximum object size 9223372036854775807", caused by insufficient data flow
320 analysis and value propagation of the 'width_add' expansion when GCC is not
321 optimizing. Cf. <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88443>. */
322 #if __GNUC__ >= 7 && !__OPTIMIZE__
323 # pragma GCC diagnostic ignored "-Wstringop-overflow"
324 #endif
326 #if FPRINTFTIME
327 static void
328 fwrite_lowcase (FILE *fp, const CHAR_T *src, size_t len)
330 while (len-- > 0)
332 fputc (TOLOWER ((UCHAR_T) *src, loc), fp);
333 ++src;
337 static void
338 fwrite_uppcase (FILE *fp, const CHAR_T *src, size_t len)
340 while (len-- > 0)
342 fputc (TOUPPER ((UCHAR_T) *src, loc), fp);
343 ++src;
346 #else
347 static CHAR_T *memcpy_lowcase (CHAR_T *dest, const CHAR_T *src,
348 size_t len LOCALE_PARAM);
350 static CHAR_T *
351 memcpy_lowcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM)
353 while (len-- > 0)
354 dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
355 return dest;
358 static CHAR_T *memcpy_uppcase (CHAR_T *dest, const CHAR_T *src,
359 size_t len LOCALE_PARAM);
361 static CHAR_T *
362 memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM)
364 while (len-- > 0)
365 dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
366 return dest;
368 #endif
371 #if USE_C_LOCALE && HAVE_STRFTIME_L
373 /* Cache for the C locale object.
374 Marked volatile so that different threads see the same value
375 (avoids locking). */
376 static volatile locale_t c_locale_cache;
378 /* Return the C locale object, or (locale_t) 0 with errno set
379 if it cannot be created. */
380 static locale_t
381 c_locale (void)
383 if (!c_locale_cache)
384 c_locale_cache = newlocale (LC_ALL_MASK, "C", (locale_t) 0);
385 return c_locale_cache;
388 #endif
391 #if (defined __NetBSD__ || defined __sun) && REQUIRE_GNUISH_STRFTIME_AM_PM
393 /* Return true if an AM/PM indicator should be removed. */
394 static bool
395 should_remove_ampm (void)
397 /* According to glibc's 'am_pm' attribute in the locale database, an AM/PM
398 indicator should be absent in the locales for the following languages:
399 ab an ast az be ber bg br bs ce cs csb cv da de dsb eo et eu fa fi fo fr
400 fur fy ga gl gv hr hsb ht hu hy it ka kk kl ku kv kw ky lb lg li lij ln
401 lt lv mg mhr mi mk mn ms mt nb nds nhn nl nn nr nso oc os pap pl pt ro
402 ru rw sah sc se sgs sk sl sm sr ss st su sv szl tg tk tn ts tt ug uk unm
403 uz ve wae wo xh zu */
404 const char *loc = gl_locale_name_unsafe (LC_TIME, "LC_TIME");
405 bool remove_ampm = false;
406 switch (loc[0])
408 case 'a':
409 switch (loc[1])
411 case 'b': case 'n': case 'z':
412 if (loc[2] == '\0' || loc[2] == '_')
413 remove_ampm = true;
414 break;
415 case 's':
416 if (loc[2] == 't' && (loc[3] == '\0' || loc[3] == '_'))
417 remove_ampm = true;
418 break;
419 default:
420 break;
422 break;
423 case 'b':
424 switch (loc[1])
426 case 'e':
427 if (loc[2] == '\0' || loc[2] == '_'
428 || (loc[2] == 'r' && (loc[3] == '\0' || loc[3] == '_')))
429 remove_ampm = true;
430 break;
431 case 'g': case 'r': case 's':
432 if (loc[2] == '\0' || loc[2] == '_')
433 remove_ampm = true;
434 break;
435 default:
436 break;
438 break;
439 case 'c':
440 switch (loc[1])
442 case 'e': case 'v':
443 if (loc[2] == '\0' || loc[2] == '_')
444 remove_ampm = true;
445 break;
446 case 's':
447 if (loc[2] == '\0' || loc[2] == '_'
448 || (loc[2] == 'b' && (loc[3] == '\0' || loc[3] == '_')))
449 remove_ampm = true;
450 break;
451 default:
452 break;
454 break;
455 case 'd':
456 switch (loc[1])
458 case 'a': case 'e':
459 if (loc[2] == '\0' || loc[2] == '_')
460 remove_ampm = true;
461 break;
462 case 's':
463 if (loc[2] == 'b' && (loc[3] == '\0' || loc[3] == '_'))
464 remove_ampm = true;
465 break;
466 default:
467 break;
469 break;
470 case 'e':
471 switch (loc[1])
473 case 'o': case 't': case 'u':
474 if (loc[2] == '\0' || loc[2] == '_')
475 remove_ampm = true;
476 break;
477 default:
478 break;
480 break;
481 case 'f':
482 switch (loc[1])
484 case 'a': case 'i': case 'o': case 'r': case 'y':
485 if (loc[2] == '\0' || loc[2] == '_')
486 remove_ampm = true;
487 break;
488 case 'u':
489 if (loc[2] == 'r' && (loc[3] == '\0' || loc[3] == '_'))
490 remove_ampm = true;
491 break;
492 default:
493 break;
495 break;
496 case 'g':
497 switch (loc[1])
499 case 'a': case 'l': case 'v':
500 if (loc[2] == '\0' || loc[2] == '_')
501 remove_ampm = true;
502 break;
503 default:
504 break;
506 break;
507 case 'h':
508 switch (loc[1])
510 case 'r': case 't': case 'u': case 'y':
511 if (loc[2] == '\0' || loc[2] == '_')
512 remove_ampm = true;
513 break;
514 case 's':
515 if (loc[2] == 'b' && (loc[3] == '\0' || loc[3] == '_'))
516 remove_ampm = true;
517 break;
518 default:
519 break;
521 break;
522 case 'i':
523 switch (loc[1])
525 case 't':
526 if (loc[2] == '\0' || loc[2] == '_')
527 remove_ampm = true;
528 break;
529 default:
530 break;
532 break;
533 case 'k':
534 switch (loc[1])
536 case 'a': case 'k': case 'l': case 'u': case 'v': case 'w': case 'y':
537 if (loc[2] == '\0' || loc[2] == '_')
538 remove_ampm = true;
539 break;
540 default:
541 break;
543 break;
544 case 'l':
545 switch (loc[1])
547 case 'b': case 'g': case 'n': case 't': case 'v':
548 if (loc[2] == '\0' || loc[2] == '_')
549 remove_ampm = true;
550 break;
551 case 'i':
552 if (loc[2] == 'j' && (loc[3] == '\0' || loc[3] == '_'))
553 remove_ampm = true;
554 break;
555 default:
556 break;
558 break;
559 case 'm':
560 switch (loc[1])
562 case 'g': case 'i': case 'k': case 'n': case 's': case 't':
563 if (loc[2] == '\0' || loc[2] == '_')
564 remove_ampm = true;
565 break;
566 case 'h':
567 if (loc[2] == 'r' && (loc[3] == '\0' || loc[3] == '_'))
568 remove_ampm = true;
569 break;
570 default:
571 break;
573 break;
574 case 'n':
575 switch (loc[1])
577 case 'b': case 'l': case 'n': case 'r':
578 if (loc[2] == '\0' || loc[2] == '_')
579 remove_ampm = true;
580 break;
581 case 'd':
582 if (loc[2] == 's' && (loc[3] == '\0' || loc[3] == '_'))
583 remove_ampm = true;
584 break;
585 case 'h':
586 if (loc[2] == 'n' && (loc[3] == '\0' || loc[3] == '_'))
587 remove_ampm = true;
588 break;
589 case 's':
590 if (loc[2] == 'o' && (loc[3] == '\0' || loc[3] == '_'))
591 remove_ampm = true;
592 break;
593 default:
594 break;
596 break;
597 case 'o':
598 switch (loc[1])
600 case 'c': case 's':
601 if (loc[2] == '\0' || loc[2] == '_')
602 remove_ampm = true;
603 break;
604 default:
605 break;
607 break;
608 case 'p':
609 switch (loc[1])
611 case 'l': case 't':
612 if (loc[2] == '\0' || loc[2] == '_')
613 remove_ampm = true;
614 break;
615 case 'a':
616 if (loc[2] == 'p' && (loc[3] == '\0' || loc[3] == '_'))
617 remove_ampm = true;
618 break;
619 default:
620 break;
622 break;
623 case 'r':
624 switch (loc[1])
626 case 'o': case 'u': case 'w':
627 if (loc[2] == '\0' || loc[2] == '_')
628 remove_ampm = true;
629 break;
630 default:
631 break;
633 break;
634 case 's':
635 switch (loc[1])
637 case 'c': case 'e': case 'k': case 'l': case 'm': case 'r': case 's':
638 case 't': case 'u': case 'v':
639 if (loc[2] == '\0' || loc[2] == '_')
640 remove_ampm = true;
641 break;
642 case 'a':
643 if (loc[2] == 'h' && (loc[3] == '\0' || loc[3] == '_'))
644 remove_ampm = true;
645 break;
646 case 'g':
647 if (loc[2] == 's' && (loc[3] == '\0' || loc[3] == '_'))
648 remove_ampm = true;
649 break;
650 case 'z':
651 if (loc[2] == 'l' && (loc[3] == '\0' || loc[3] == '_'))
652 remove_ampm = true;
653 break;
654 default:
655 break;
657 break;
658 case 't':
659 switch (loc[1])
661 case 'g': case 'k': case 'n': case 's': case 't':
662 if (loc[2] == '\0' || loc[2] == '_')
663 remove_ampm = true;
664 break;
665 default:
666 break;
668 break;
669 case 'u':
670 switch (loc[1])
672 case 'g': case 'k': case 'z':
673 if (loc[2] == '\0' || loc[2] == '_')
674 remove_ampm = true;
675 break;
676 case 'n':
677 if (loc[2] == 'm'&& (loc[3] == '\0' || loc[3] == '_'))
678 remove_ampm = true;
679 break;
680 default:
681 break;
683 break;
684 case 'v':
685 switch (loc[1])
687 case 'e':
688 if (loc[2] == '\0' || loc[2] == '_')
689 remove_ampm = true;
690 break;
691 default:
692 break;
694 break;
695 case 'w':
696 switch (loc[1])
698 case 'a':
699 if (loc[2] == 'e' && (loc[3] == '\0' || loc[3] == '_'))
700 remove_ampm = true;
701 break;
702 case 'o':
703 if (loc[2] == '\0' || loc[2] == '_')
704 remove_ampm = true;
705 break;
706 default:
707 break;
709 break;
710 case 'x':
711 switch (loc[1])
713 case 'h':
714 if (loc[2] == '\0' || loc[2] == '_')
715 remove_ampm = true;
716 break;
717 default:
718 break;
720 break;
721 case 'z':
722 switch (loc[1])
724 case 'u':
725 if (loc[2] == '\0' || loc[2] == '_')
726 remove_ampm = true;
727 break;
728 default:
729 break;
731 break;
732 default:
733 break;
735 return remove_ampm;
738 #endif
741 #if ! HAVE_TM_GMTOFF
742 /* Yield the difference between *A and *B,
743 measured in seconds, ignoring leap seconds. */
744 # define tm_diff ftime_tm_diff
745 static int tm_diff (const struct tm *, const struct tm *);
746 static int
747 tm_diff (const struct tm *a, const struct tm *b)
749 /* Compute intervening leap days correctly even if year is negative.
750 Take care to avoid int overflow in leap day calculations,
751 but it's OK to assume that A and B are close to each other. */
752 int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3);
753 int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3);
754 int a100 = (a4 + (a4 < 0)) / 25 - (a4 < 0);
755 int b100 = (b4 + (b4 < 0)) / 25 - (b4 < 0);
756 int a400 = SHR (a100, 2);
757 int b400 = SHR (b100, 2);
758 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
759 int years = a->tm_year - b->tm_year;
760 int days = (365 * years + intervening_leap_days
761 + (a->tm_yday - b->tm_yday));
762 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
763 + (a->tm_min - b->tm_min))
764 + (a->tm_sec - b->tm_sec));
766 #endif /* ! HAVE_TM_GMTOFF */
770 /* The number of days from the first day of the first ISO week of this
771 year to the year day YDAY with week day WDAY. ISO weeks start on
772 Monday; the first ISO week has the year's first Thursday. YDAY may
773 be as small as YDAY_MINIMUM. */
774 #define ISO_WEEK_START_WDAY 1 /* Monday */
775 #define ISO_WEEK1_WDAY 4 /* Thursday */
776 #define YDAY_MINIMUM (-366)
777 static int iso_week_days (int, int);
778 static __inline int
779 iso_week_days (int yday, int wday)
781 /* Add enough to the first operand of % to make it nonnegative. */
782 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
783 return (yday
784 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
785 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
789 #if !defined _NL_CURRENT && (USE_C_LOCALE && !HAVE_STRFTIME_L)
790 static CHAR_T const c_weekday_names[][sizeof "Wednesday"] =
792 L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
793 L_("Thursday"), L_("Friday"), L_("Saturday")
795 static CHAR_T const c_month_names[][sizeof "September"] =
797 L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
798 L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
799 L_("November"), L_("December")
801 #endif
804 /* When compiling this file, GNU applications can #define my_strftime
805 to a symbol (typically nstrftime) to get an extended strftime with
806 extra arguments TZ and NS. */
808 #ifdef my_strftime
809 # define extra_args , tz, ns
810 # define extra_args_spec , timezone_t tz, int ns
811 #else
812 # if defined COMPILE_WIDE
813 # define my_strftime wcsftime
814 # define nl_get_alt_digit _nl_get_walt_digit
815 # else
816 # define my_strftime strftime
817 # define nl_get_alt_digit _nl_get_alt_digit
818 # endif
819 # define extra_args
820 # define extra_args_spec
821 /* We don't have this information in general. */
822 # define tz 1
823 # define ns 0
824 #endif
826 static size_t __strftime_internal (STREAM_OR_CHAR_T *, STRFTIME_ARG (size_t)
827 const CHAR_T *, const struct tm *,
828 bool, int, int, bool *
829 extra_args_spec LOCALE_PARAM);
831 /* Write information from TP into S according to the format
832 string FORMAT, writing no more that MAXSIZE characters
833 (including the terminating '\0') and returning number of
834 characters written. If S is NULL, nothing will be written
835 anywhere, so to determine how many characters would be
836 written, use NULL for S and (size_t) -1 for MAXSIZE. */
837 size_t
838 my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
839 const CHAR_T *format,
840 const struct tm *tp extra_args_spec LOCALE_PARAM)
842 bool tzset_called = false;
843 return __strftime_internal (s, STRFTIME_ARG (maxsize) format, tp, false,
844 0, -1, &tzset_called extra_args LOCALE_ARG);
846 libc_hidden_def (my_strftime)
848 /* Just like my_strftime, above, but with more parameters.
849 UPCASE indicates that the result should be converted to upper case.
850 YR_SPEC and WIDTH specify the padding and width for the year.
851 *TZSET_CALLED indicates whether tzset has been called here. */
852 static size_t
853 __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
854 const CHAR_T *format,
855 const struct tm *tp, bool upcase,
856 int yr_spec, int width, bool *tzset_called
857 extra_args_spec LOCALE_PARAM)
859 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
860 struct __locale_data *const current = loc->__locales[LC_TIME];
861 #endif
862 #if FPRINTFTIME
863 size_t maxsize = (size_t) -1;
864 #endif
866 int saved_errno = errno;
867 int hour12 = tp->tm_hour;
868 #ifdef _NL_CURRENT
869 /* We cannot make the following values variables since we must delay
870 the evaluation of these values until really needed since some
871 expressions might not be valid in every situation. The 'struct tm'
872 might be generated by a strptime() call that initialized
873 only a few elements. Dereference the pointers only if the format
874 requires this. Then it is ok to fail if the pointers are invalid. */
875 # define a_wkday \
876 ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
877 ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)))
878 # define f_wkday \
879 ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
880 ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)))
881 # define a_month \
882 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
883 ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)))
884 # define f_month \
885 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
886 ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)))
887 # define a_altmonth \
888 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
889 ? "?" : _NL_CURRENT (LC_TIME, NLW(ABALTMON_1) + tp->tm_mon)))
890 # define f_altmonth \
891 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
892 ? "?" : _NL_CURRENT (LC_TIME, NLW(ALTMON_1) + tp->tm_mon)))
893 # define ampm \
894 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
895 ? NLW(PM_STR) : NLW(AM_STR)))
897 # define aw_len STRLEN (a_wkday)
898 # define am_len STRLEN (a_month)
899 # define aam_len STRLEN (a_altmonth)
900 # define ap_len STRLEN (ampm)
901 #elif USE_C_LOCALE && !HAVE_STRFTIME_L
902 /* The English abbreviated weekday names are just the first 3 characters of the
903 English full weekday names. */
904 # define a_wkday \
905 (tp->tm_wday < 0 || tp->tm_wday > 6 ? L_("?") : c_weekday_names[tp->tm_wday])
906 # define aw_len 3
907 # define f_wkday \
908 (tp->tm_wday < 0 || tp->tm_wday > 6 ? L_("?") : c_weekday_names[tp->tm_wday])
909 /* The English abbreviated month names are just the first 3 characters of the
910 English full month names. */
911 # define a_month \
912 (tp->tm_mon < 0 || tp->tm_mon > 11 ? L_("?") : c_month_names[tp->tm_mon])
913 # define am_len 3
914 # define f_month \
915 (tp->tm_mon < 0 || tp->tm_mon > 11 ? L_("?") : c_month_names[tp->tm_mon])
916 /* The English AM/PM strings happen to have the same length, namely 2. */
917 # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
918 # define ap_len 2
919 #endif
920 #if HAVE_TZNAME
921 char **tzname_vec = tzname;
922 #endif
923 const char *zone;
924 size_t i = 0;
925 STREAM_OR_CHAR_T *p = s;
926 const CHAR_T *f;
927 #if DO_MULTIBYTE && !defined COMPILE_WIDE
928 const char *format_end = NULL;
929 #endif
931 zone = NULL;
932 #if HAVE_STRUCT_TM_TM_ZONE
933 /* The POSIX test suite assumes that setting
934 the environment variable TZ to a new value before calling strftime()
935 will influence the result (the %Z format) even if the information in
936 TP is computed with a totally different time zone.
937 This is bogus: though POSIX allows bad behavior like this,
938 POSIX does not require it. Do the right thing instead. */
939 zone = (const char *) tp->tm_zone;
940 #endif
941 #if HAVE_TZNAME
942 if (!tz)
944 if (! (zone && *zone))
945 zone = "GMT";
947 else
949 # if !HAVE_STRUCT_TM_TM_ZONE
950 /* Infer the zone name from *TZ instead of from TZNAME. */
951 tzname_vec = tz->tzname_copy;
952 # endif
954 /* The tzset() call might have changed the value. */
955 if (!(zone && *zone) && tp->tm_isdst >= 0)
957 /* POSIX.1 requires that local time zone information be used as
958 though strftime called tzset. */
959 # ifndef my_strftime
960 if (!*tzset_called)
962 tzset ();
963 *tzset_called = true;
965 # endif
966 zone = tzname_vec[tp->tm_isdst != 0];
968 #endif
969 if (! zone)
970 zone = "";
972 if (hour12 > 12)
973 hour12 -= 12;
974 else
975 if (hour12 == 0)
976 hour12 = 12;
978 for (f = format; *f != '\0'; width = -1, f++)
980 int pad = 0; /* Padding for number ('_', '-', '+', '0', or 0). */
981 int modifier; /* Field modifier ('E', 'O', or 0). */
982 int digits = 0; /* Max digits for numeric format. */
983 int number_value; /* Numeric value to be printed. */
984 unsigned int u_number_value; /* (unsigned int) number_value. */
985 bool negative_number; /* The number is negative. */
986 bool always_output_a_sign; /* +/- should always be output. */
987 int tz_colon_mask; /* Bitmask of where ':' should appear. */
988 const CHAR_T *subfmt;
989 CHAR_T *bufp;
990 CHAR_T buf[1
991 + 2 /* for the two colons in a %::z or %:::z time zone */
992 + (sizeof (int) < sizeof (time_t)
993 ? INT_STRLEN_BOUND (time_t)
994 : INT_STRLEN_BOUND (int))];
995 bool to_lowcase = false;
996 bool to_uppcase = upcase;
997 size_t colons;
998 bool change_case = false;
999 int format_char;
1000 int subwidth;
1002 #if DO_MULTIBYTE && !defined COMPILE_WIDE
1003 switch (*f)
1005 case L_('%'):
1006 break;
1008 case L_('\b'): case L_('\t'): case L_('\n'):
1009 case L_('\v'): case L_('\f'): case L_('\r'):
1010 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
1011 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
1012 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
1013 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
1014 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
1015 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
1016 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
1017 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
1018 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
1019 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
1020 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
1021 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
1022 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
1023 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
1024 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
1025 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
1026 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
1027 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
1028 case L_('~'):
1029 /* The C Standard requires these 98 characters (plus '%') to
1030 be in the basic execution character set. None of these
1031 characters can start a multibyte sequence, so they need
1032 not be analyzed further. */
1033 add1 (*f);
1034 continue;
1036 default:
1037 /* Copy this multibyte sequence until we reach its end, find
1038 an error, or come back to the initial shift state. */
1040 mbstate_t mbstate = mbstate_zero;
1041 size_t len = 0;
1042 size_t fsize;
1044 if (! format_end)
1045 format_end = f + strlen (f) + 1;
1046 fsize = format_end - f;
1050 size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
1052 if (bytes == 0)
1053 break;
1055 if (bytes == (size_t) -2)
1057 len += strlen (f + len);
1058 break;
1061 if (bytes == (size_t) -1)
1063 len++;
1064 break;
1067 len += bytes;
1069 while (! mbsinit (&mbstate));
1071 cpy (len, f);
1072 f += len - 1;
1073 continue;
1077 #else /* ! DO_MULTIBYTE */
1079 /* Either multibyte encodings are not supported, they are
1080 safe for formats, so any non-'%' byte can be copied through,
1081 or this is the wide character version. */
1082 if (*f != L_('%'))
1084 add1 (*f);
1085 continue;
1088 #endif /* ! DO_MULTIBYTE */
1090 char const *percent = f;
1092 /* Check for flags that can modify a format. */
1093 while (1)
1095 switch (*++f)
1097 /* This influences the number formats. */
1098 case L_('_'):
1099 case L_('-'):
1100 case L_('+'):
1101 case L_('0'):
1102 pad = *f;
1103 continue;
1105 /* This changes textual output. */
1106 case L_('^'):
1107 to_uppcase = true;
1108 continue;
1109 case L_('#'):
1110 change_case = true;
1111 continue;
1113 default:
1114 break;
1116 break;
1119 if (ISDIGIT (*f))
1121 width = 0;
1124 if (ckd_mul (&width, width, 10)
1125 || ckd_add (&width, width, *f - L_('0')))
1126 width = INT_MAX;
1127 ++f;
1129 while (ISDIGIT (*f));
1132 /* Check for modifiers. */
1133 switch (*f)
1135 case L_('E'):
1136 case L_('O'):
1137 modifier = *f++;
1138 break;
1140 default:
1141 modifier = 0;
1142 break;
1145 /* Now do the specified format. */
1146 format_char = *f;
1147 switch (format_char)
1149 #define DO_NUMBER(d, v) \
1150 do \
1152 digits = d; \
1153 number_value = v; \
1154 goto do_number; \
1156 while (0)
1157 #define DO_SIGNED_NUMBER(d, negative, v) \
1158 DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_signed_number)
1159 #define DO_YEARISH(d, negative, v) \
1160 DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_yearish)
1161 #define DO_MAYBE_SIGNED_NUMBER(d, negative, v, label) \
1162 do \
1164 digits = d; \
1165 negative_number = negative; \
1166 u_number_value = v; \
1167 goto label; \
1169 while (0)
1171 /* The mask is not what you might think.
1172 When the ordinal i'th bit is set, insert a colon
1173 before the i'th digit of the time zone representation. */
1174 #define DO_TZ_OFFSET(d, mask, v) \
1175 do \
1177 digits = d; \
1178 tz_colon_mask = mask; \
1179 u_number_value = v; \
1180 goto do_tz_offset; \
1182 while (0)
1183 #define DO_NUMBER_SPACEPAD(d, v) \
1184 do \
1186 digits = d; \
1187 number_value = v; \
1188 goto do_number_spacepad; \
1190 while (0)
1192 case L_('%'):
1193 if (f - 1 != percent)
1194 goto bad_percent;
1195 add1 (*f);
1196 break;
1198 case L_('a'):
1199 if (modifier != 0)
1200 goto bad_format;
1201 if (change_case)
1203 to_uppcase = true;
1204 to_lowcase = false;
1206 #if defined _NL_CURRENT || (USE_C_LOCALE && !HAVE_STRFTIME_L)
1207 cpy (aw_len, a_wkday);
1208 break;
1209 #else
1210 goto underlying_strftime;
1211 #endif
1213 case 'A':
1214 if (modifier != 0)
1215 goto bad_format;
1216 if (change_case)
1218 to_uppcase = true;
1219 to_lowcase = false;
1221 #if defined _NL_CURRENT || (USE_C_LOCALE && !HAVE_STRFTIME_L)
1222 cpy (STRLEN (f_wkday), f_wkday);
1223 break;
1224 #else
1225 goto underlying_strftime;
1226 #endif
1228 case L_('b'):
1229 case L_('h'):
1230 if (change_case)
1232 to_uppcase = true;
1233 to_lowcase = false;
1235 if (modifier == L_('E'))
1236 goto bad_format;
1237 #ifdef _NL_CURRENT
1238 if (modifier == L_('O'))
1239 cpy (aam_len, a_altmonth);
1240 else
1241 cpy (am_len, a_month);
1242 break;
1243 #elif USE_C_LOCALE && !HAVE_STRFTIME_L
1244 cpy (am_len, a_month);
1245 break;
1246 #else
1247 goto underlying_strftime;
1248 #endif
1250 case L_('B'):
1251 if (modifier == L_('E'))
1252 goto bad_format;
1253 if (change_case)
1255 to_uppcase = true;
1256 to_lowcase = false;
1258 #ifdef _NL_CURRENT
1259 if (modifier == L_('O'))
1260 cpy (STRLEN (f_altmonth), f_altmonth);
1261 else
1262 cpy (STRLEN (f_month), f_month);
1263 break;
1264 #elif USE_C_LOCALE && !HAVE_STRFTIME_L
1265 cpy (STRLEN (f_month), f_month);
1266 break;
1267 #else
1268 goto underlying_strftime;
1269 #endif
1271 case L_('c'):
1272 if (modifier == L_('O'))
1273 goto bad_format;
1274 #ifdef _NL_CURRENT
1275 if (! (modifier == L_('E')
1276 && (*(subfmt =
1277 (const CHAR_T *) _NL_CURRENT (LC_TIME,
1278 NLW(ERA_D_T_FMT)))
1279 != '\0')))
1280 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
1281 #elif USE_C_LOCALE && !HAVE_STRFTIME_L
1282 subfmt = L_("%a %b %e %H:%M:%S %Y");
1283 #else
1284 goto underlying_strftime;
1285 #endif
1287 subformat:
1288 subwidth = -1;
1289 subformat_width:
1291 size_t len = __strftime_internal (NULL, STRFTIME_ARG ((size_t) -1)
1292 subfmt, tp, to_uppcase,
1293 pad, subwidth, tzset_called
1294 extra_args LOCALE_ARG);
1295 add (len, __strftime_internal (p,
1296 STRFTIME_ARG (maxsize - i)
1297 subfmt, tp, to_uppcase,
1298 pad, subwidth, tzset_called
1299 extra_args LOCALE_ARG));
1301 break;
1303 #if !((defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY) || (USE_C_LOCALE && !HAVE_STRFTIME_L))
1304 underlying_strftime:
1306 /* The relevant information is available only via the
1307 underlying strftime implementation, so use that. */
1308 char ufmt[5];
1309 char *u = ufmt;
1310 char ubuf[1024]; /* enough for any single format in practice */
1311 size_t len;
1312 /* Make sure we're calling the actual underlying strftime.
1313 In some cases, config.h contains something like
1314 "#define strftime rpl_strftime". */
1315 # ifdef strftime
1316 # undef strftime
1317 size_t strftime (char *, size_t, const char *, struct tm const *);
1318 # endif
1320 /* The space helps distinguish strftime failure from empty
1321 output. */
1322 *u++ = ' ';
1323 *u++ = '%';
1324 if (modifier != 0)
1325 *u++ = modifier;
1326 *u++ = format_char;
1327 *u = '\0';
1329 # if USE_C_LOCALE /* implies HAVE_STRFTIME_L */
1330 locale_t locale = c_locale ();
1331 if (!locale)
1332 return 0; /* errno is set here */
1333 len = strftime_l (ubuf, sizeof ubuf, ufmt, tp, locale);
1334 # else
1335 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
1336 # endif
1337 if (len != 0)
1339 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ < 31) || defined __NetBSD__ || defined __sun /* glibc < 2.31, NetBSD, Solaris */
1340 if (format_char == L_('c'))
1342 /* The output of the strftime %c directive consists of the
1343 date, the time, and the time zone. But the time zone is
1344 wrong, since neither TZ nor ZONE was passed as argument.
1345 Therefore, remove the the last space-delimited word.
1346 In order not to accidentally remove a date or a year
1347 (that contains no letter) or an AM/PM indicator (that has
1348 length 2), remove that last word only if it contains a
1349 letter and has length >= 3. */
1350 char *space;
1351 for (space = ubuf + len - 1; *space != ' '; space--)
1353 if (space > ubuf)
1355 /* Found a space. */
1356 if (strlen (space + 1) >= 3)
1358 /* The last word has length >= 3. */
1359 bool found_letter = false;
1360 const char *p;
1361 for (p = space + 1; *p != '\0'; p++)
1362 if ((*p >= 'A' && *p <= 'Z')
1363 || (*p >= 'a' && *p <= 'z'))
1365 found_letter = true;
1366 break;
1368 if (found_letter)
1370 /* The last word contains a letter. */
1371 *space = '\0';
1372 len = space - ubuf;
1377 # if (defined __NetBSD__ || defined __sun) && REQUIRE_GNUISH_STRFTIME_AM_PM
1378 /* The output of the strftime %p and %r directives contains
1379 an AM/PM indicator even for locales where it is not
1380 suitable, such as French. Remove this indicator. */
1381 else if (format_char == L_('p'))
1383 bool found_ampm = (len > 1);
1384 if (found_ampm && should_remove_ampm ())
1386 ubuf[1] = '\0';
1387 len = 1;
1390 else if (format_char == L_('r'))
1392 char last_char = ubuf[len - 1];
1393 bool found_ampm = !(last_char >= '0' && last_char <= '9');
1394 if (found_ampm && should_remove_ampm ())
1396 char *space;
1397 for (space = ubuf + len - 1; *space != ' '; space--)
1399 if (space > ubuf)
1401 *space = '\0';
1402 len = space - ubuf;
1406 # endif
1407 # endif
1408 cpy (len - 1, ubuf + 1);
1411 break;
1412 #endif
1414 case L_('C'):
1415 if (modifier == L_('E'))
1417 #if HAVE_STRUCT_ERA_ENTRY
1418 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1419 if (era)
1421 # ifdef COMPILE_WIDE
1422 size_t len = __wcslen (era->era_wname);
1423 cpy (len, era->era_wname);
1424 # else
1425 size_t len = strlen (era->era_name);
1426 cpy (len, era->era_name);
1427 # endif
1428 break;
1430 #elif USE_C_LOCALE && !HAVE_STRFTIME_L
1431 #else
1432 goto underlying_strftime;
1433 #endif
1437 bool negative_year = tp->tm_year < - TM_YEAR_BASE;
1438 bool zero_thru_1899 = !negative_year & (tp->tm_year < 0);
1439 int century = ((tp->tm_year - 99 * zero_thru_1899) / 100
1440 + TM_YEAR_BASE / 100);
1441 DO_YEARISH (2, negative_year, century);
1444 case L_('x'):
1445 if (modifier == L_('O'))
1446 goto bad_format;
1447 #ifdef _NL_CURRENT
1448 if (! (modifier == L_('E')
1449 && (*(subfmt =
1450 (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
1451 != L_('\0'))))
1452 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
1453 goto subformat;
1454 #elif USE_C_LOCALE && !HAVE_STRFTIME_L
1455 subfmt = L_("%m/%d/%y");
1456 goto subformat;
1457 #else
1458 goto underlying_strftime;
1459 #endif
1460 case L_('D'):
1461 if (modifier != 0)
1462 goto bad_format;
1463 subfmt = L_("%m/%d/%y");
1464 goto subformat;
1466 case L_('d'):
1467 if (modifier == L_('E'))
1468 goto bad_format;
1470 DO_NUMBER (2, tp->tm_mday);
1472 case L_('e'):
1473 if (modifier == L_('E'))
1474 goto bad_format;
1476 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
1478 /* All numeric formats set DIGITS and NUMBER_VALUE (or U_NUMBER_VALUE)
1479 and then jump to one of these labels. */
1481 do_tz_offset:
1482 always_output_a_sign = true;
1483 goto do_number_body;
1485 do_yearish:
1486 if (pad == 0)
1487 pad = yr_spec;
1488 always_output_a_sign
1489 = (pad == L_('+')
1490 && ((digits == 2 ? 99 : 9999) < u_number_value
1491 || digits < width));
1492 goto do_maybe_signed_number;
1494 do_number_spacepad:
1495 if (pad == 0)
1496 pad = L_('_');
1498 do_number:
1499 /* Format NUMBER_VALUE according to the MODIFIER flag. */
1500 negative_number = number_value < 0;
1501 u_number_value = number_value;
1503 do_signed_number:
1504 always_output_a_sign = false;
1506 do_maybe_signed_number:
1507 tz_colon_mask = 0;
1509 do_number_body:
1510 /* Format U_NUMBER_VALUE according to the MODIFIER flag.
1511 NEGATIVE_NUMBER is nonzero if the original number was
1512 negative; in this case it was converted directly to
1513 unsigned int (i.e., modulo (UINT_MAX + 1)) without
1514 negating it. */
1515 if (modifier == L_('O') && !negative_number)
1517 #ifdef _NL_CURRENT
1518 /* Get the locale specific alternate representation of
1519 the number. If none exist NULL is returned. */
1520 const CHAR_T *cp = nl_get_alt_digit (u_number_value
1521 HELPER_LOCALE_ARG);
1523 if (cp != NULL)
1525 size_t digitlen = STRLEN (cp);
1526 if (digitlen != 0)
1528 cpy (digitlen, cp);
1529 break;
1532 #elif USE_C_LOCALE && !HAVE_STRFTIME_L
1533 #else
1534 goto underlying_strftime;
1535 #endif
1538 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1540 if (negative_number)
1541 u_number_value = - u_number_value;
1545 if (tz_colon_mask & 1)
1546 *--bufp = ':';
1547 tz_colon_mask >>= 1;
1548 *--bufp = u_number_value % 10 + L_('0');
1549 u_number_value /= 10;
1551 while (u_number_value != 0 || tz_colon_mask != 0);
1553 do_number_sign_and_padding:
1554 if (pad == 0)
1555 pad = L_('0');
1556 if (width < 0)
1557 width = digits;
1560 CHAR_T sign_char = (negative_number ? L_('-')
1561 : always_output_a_sign ? L_('+')
1562 : 0);
1563 int numlen = buf + sizeof buf / sizeof buf[0] - bufp;
1564 int shortage = width - !!sign_char - numlen;
1565 int padding = pad == L_('-') || shortage <= 0 ? 0 : shortage;
1567 if (sign_char)
1569 if (pad == L_('_'))
1571 if (p)
1572 memset_space (p, padding);
1573 i += padding;
1574 width -= padding;
1576 width_add1 (0, sign_char);
1577 width--;
1580 cpy (numlen, bufp);
1582 break;
1584 case L_('F'):
1585 if (modifier != 0)
1586 goto bad_format;
1587 if (pad == 0 && width < 0)
1589 pad = L_('+');
1590 subwidth = 4;
1592 else
1594 subwidth = width - 6;
1595 if (subwidth < 0)
1596 subwidth = 0;
1598 subfmt = L_("%Y-%m-%d");
1599 goto subformat_width;
1601 case L_('H'):
1602 if (modifier == L_('E'))
1603 goto bad_format;
1605 DO_NUMBER (2, tp->tm_hour);
1607 case L_('I'):
1608 if (modifier == L_('E'))
1609 goto bad_format;
1611 DO_NUMBER (2, hour12);
1613 case L_('k'): /* GNU extension. */
1614 if (modifier == L_('E'))
1615 goto bad_format;
1617 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1619 case L_('l'): /* GNU extension. */
1620 if (modifier == L_('E'))
1621 goto bad_format;
1623 DO_NUMBER_SPACEPAD (2, hour12);
1625 case L_('j'):
1626 if (modifier == L_('E'))
1627 goto bad_format;
1629 DO_SIGNED_NUMBER (3, tp->tm_yday < -1, tp->tm_yday + 1U);
1631 case L_('M'):
1632 if (modifier == L_('E'))
1633 goto bad_format;
1635 DO_NUMBER (2, tp->tm_min);
1637 case L_('m'):
1638 if (modifier == L_('E'))
1639 goto bad_format;
1641 DO_SIGNED_NUMBER (2, tp->tm_mon < -1, tp->tm_mon + 1U);
1643 #ifndef _LIBC
1644 case L_('N'): /* GNU extension. */
1645 if (modifier == L_('E'))
1646 goto bad_format;
1648 int n = ns, ns_digits = 9;
1649 if (width <= 0)
1650 width = ns_digits;
1651 int ndigs = ns_digits;
1652 while (width < ndigs || (1 < ndigs && n % 10 == 0))
1653 ndigs--, n /= 10;
1654 for (int j = ndigs; 0 < j; j--)
1655 buf[j - 1] = n % 10 + L_('0'), n /= 10;
1656 if (!pad)
1657 pad = L_('0');
1658 width_cpy (0, ndigs, buf);
1659 width_add (width - ndigs, 0, (void) 0);
1661 break;
1662 #endif
1664 case L_('n'):
1665 add1 (L_('\n'));
1666 break;
1668 case L_('P'):
1669 to_lowcase = true;
1670 #ifndef _NL_CURRENT
1671 format_char = L_('p');
1672 #endif
1673 FALLTHROUGH;
1674 case L_('p'):
1675 if (change_case)
1677 to_uppcase = false;
1678 to_lowcase = true;
1680 #if defined _NL_CURRENT || (USE_C_LOCALE && !HAVE_STRFTIME_L)
1681 cpy (ap_len, ampm);
1682 break;
1683 #else
1684 goto underlying_strftime;
1685 #endif
1687 case L_('q'): /* GNU extension. */
1688 DO_SIGNED_NUMBER (1, false, ((tp->tm_mon * 11) >> 5) + 1);
1690 case L_('R'):
1691 subfmt = L_("%H:%M");
1692 goto subformat;
1694 case L_('r'):
1695 #ifdef _NL_CURRENT
1696 if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1697 NLW(T_FMT_AMPM)))
1698 == L_('\0'))
1699 subfmt = L_("%I:%M:%S %p");
1700 goto subformat;
1701 #elif USE_C_LOCALE && !HAVE_STRFTIME_L
1702 subfmt = L_("%I:%M:%S %p");
1703 goto subformat;
1704 #elif (defined __APPLE__ && defined __MACH__) || defined __FreeBSD__
1705 /* macOS, FreeBSD strftime() may produce empty output for "%r". */
1706 subfmt = L_("%I:%M:%S %p");
1707 goto subformat;
1708 #else
1709 goto underlying_strftime;
1710 #endif
1712 case L_('S'):
1713 if (modifier == L_('E'))
1714 goto bad_format;
1716 DO_NUMBER (2, tp->tm_sec);
1718 case L_('s'): /* GNU extension. */
1720 struct tm ltm;
1721 time_t t;
1723 ltm = *tp;
1724 ltm.tm_yday = -1;
1725 t = mktime_z (tz, &ltm);
1726 if (ltm.tm_yday < 0)
1728 errno = EOVERFLOW;
1729 return 0;
1732 /* Generate string value for T using time_t arithmetic;
1733 this works even if sizeof (long) < sizeof (time_t). */
1735 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1736 negative_number = t < 0;
1740 int d = t % 10;
1741 t /= 10;
1742 *--bufp = (negative_number ? -d : d) + L_('0');
1744 while (t != 0);
1746 digits = 1;
1747 always_output_a_sign = false;
1748 goto do_number_sign_and_padding;
1751 case L_('X'):
1752 if (modifier == L_('O'))
1753 goto bad_format;
1754 #ifdef _NL_CURRENT
1755 if (! (modifier == L_('E')
1756 && (*(subfmt =
1757 (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1758 != L_('\0'))))
1759 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1760 goto subformat;
1761 #elif USE_C_LOCALE && !HAVE_STRFTIME_L
1762 subfmt = L_("%H:%M:%S");
1763 goto subformat;
1764 #else
1765 goto underlying_strftime;
1766 #endif
1767 case L_('T'):
1768 subfmt = L_("%H:%M:%S");
1769 goto subformat;
1771 case L_('t'):
1772 add1 (L_('\t'));
1773 break;
1775 case L_('u'):
1776 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1778 case L_('U'):
1779 if (modifier == L_('E'))
1780 goto bad_format;
1782 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1784 case L_('V'):
1785 case L_('g'):
1786 case L_('G'):
1787 if (modifier == L_('E'))
1788 goto bad_format;
1790 /* YEAR is a leap year if and only if (tp->tm_year + TM_YEAR_BASE)
1791 is a leap year, except that YEAR and YEAR - 1 both work
1792 correctly even when (tp->tm_year + TM_YEAR_BASE) would
1793 overflow. */
1794 int year = (tp->tm_year
1795 + (tp->tm_year < 0
1796 ? TM_YEAR_BASE % 400
1797 : TM_YEAR_BASE % 400 - 400));
1798 int year_adjust = 0;
1799 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1801 if (days < 0)
1803 /* This ISO week belongs to the previous year. */
1804 year_adjust = -1;
1805 days = iso_week_days (tp->tm_yday + (365 + __isleap (year - 1)),
1806 tp->tm_wday);
1808 else
1810 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1811 tp->tm_wday);
1812 if (0 <= d)
1814 /* This ISO week belongs to the next year. */
1815 year_adjust = 1;
1816 days = d;
1820 switch (*f)
1822 case L_('g'):
1824 int yy = (tp->tm_year % 100 + year_adjust) % 100;
1825 DO_YEARISH (2, false,
1826 (0 <= yy
1827 ? yy
1828 : tp->tm_year < -TM_YEAR_BASE - year_adjust
1829 ? -yy
1830 : yy + 100));
1833 case L_('G'):
1834 DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE - year_adjust,
1835 (tp->tm_year + (unsigned int) TM_YEAR_BASE
1836 + year_adjust));
1838 default:
1839 DO_NUMBER (2, days / 7 + 1);
1843 case L_('W'):
1844 if (modifier == L_('E'))
1845 goto bad_format;
1847 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1849 case L_('w'):
1850 if (modifier == L_('E'))
1851 goto bad_format;
1853 DO_NUMBER (1, tp->tm_wday);
1855 case L_('Y'):
1856 if (modifier == L_('E'))
1858 #if HAVE_STRUCT_ERA_ENTRY
1859 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1860 if (era)
1862 # ifdef COMPILE_WIDE
1863 subfmt = era->era_wformat;
1864 # else
1865 subfmt = era->era_format;
1866 # endif
1867 if (pad == 0)
1868 pad = yr_spec;
1869 goto subformat;
1871 #elif USE_C_LOCALE && !HAVE_STRFTIME_L
1872 #else
1873 goto underlying_strftime;
1874 #endif
1876 if (modifier == L_('O'))
1877 goto bad_format;
1879 DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE,
1880 tp->tm_year + (unsigned int) TM_YEAR_BASE);
1882 case L_('y'):
1883 if (modifier == L_('E'))
1885 #if HAVE_STRUCT_ERA_ENTRY
1886 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1887 if (era)
1889 int delta = tp->tm_year - era->start_date[0];
1890 if (pad == 0)
1891 pad = yr_spec;
1892 DO_NUMBER (2, (era->offset
1893 + delta * era->absolute_direction));
1895 #elif USE_C_LOCALE && !HAVE_STRFTIME_L
1896 #else
1897 goto underlying_strftime;
1898 #endif
1902 int yy = tp->tm_year % 100;
1903 if (yy < 0)
1904 yy = tp->tm_year < - TM_YEAR_BASE ? -yy : yy + 100;
1905 DO_YEARISH (2, false, yy);
1908 case L_('Z'):
1909 if (change_case)
1911 to_uppcase = false;
1912 to_lowcase = true;
1915 #ifdef COMPILE_WIDE
1917 /* The zone string is always given in multibyte form. We have
1918 to convert it to wide character. */
1919 size_t w = pad == L_('-') || width < 0 ? 0 : width;
1920 char const *z = zone;
1921 mbstate_t st = {0};
1922 size_t len = __mbsrtowcs_l (p, &z, maxsize - i, &st, loc);
1923 if (len == (size_t) -1)
1924 return 0;
1925 size_t incr = len < w ? w : len;
1926 if (incr >= maxsize - i)
1928 errno = ERANGE;
1929 return 0;
1931 if (p)
1933 if (len < w)
1935 size_t delta = w - len;
1936 __wmemmove (p + delta, p, len);
1937 wchar_t wc = pad == L_('0') || pad == L_('+') ? L'0' : L' ';
1938 wmemset (p, wc, delta);
1940 p += incr;
1942 i += incr;
1944 #else
1945 cpy (strlen (zone), zone);
1946 #endif
1947 break;
1949 case L_(':'):
1950 /* :, ::, and ::: are valid only just before 'z'.
1951 :::: etc. are rejected later. */
1952 for (colons = 1; f[colons] == L_(':'); colons++)
1953 continue;
1954 if (f[colons] != L_('z'))
1955 goto bad_format;
1956 f += colons;
1957 goto do_z_conversion;
1959 case L_('z'):
1960 colons = 0;
1962 do_z_conversion:
1963 if (tp->tm_isdst < 0)
1964 break;
1967 int diff;
1968 int hour_diff;
1969 int min_diff;
1970 int sec_diff;
1971 #if HAVE_TM_GMTOFF
1972 diff = tp->tm_gmtoff;
1973 #else
1974 if (!tz)
1975 diff = 0;
1976 else
1978 struct tm gtm;
1979 struct tm ltm;
1980 time_t lt;
1982 /* POSIX.1 requires that local time zone information be used as
1983 though strftime called tzset. */
1984 # ifndef my_strftime
1985 if (!*tzset_called)
1987 tzset ();
1988 *tzset_called = true;
1990 # endif
1992 ltm = *tp;
1993 ltm.tm_wday = -1;
1994 lt = mktime_z (tz, &ltm);
1995 if (ltm.tm_wday < 0 || ! localtime_rz (0, &lt, &gtm))
1996 break;
1997 diff = tm_diff (&ltm, &gtm);
1999 #endif
2001 negative_number = diff < 0 || (diff == 0 && *zone == '-');
2002 hour_diff = diff / 60 / 60;
2003 min_diff = diff / 60 % 60;
2004 sec_diff = diff % 60;
2006 switch (colons)
2008 case 0: /* +hhmm */
2009 DO_TZ_OFFSET (5, 0, hour_diff * 100 + min_diff);
2011 case 1: tz_hh_mm: /* +hh:mm */
2012 DO_TZ_OFFSET (6, 04, hour_diff * 100 + min_diff);
2014 case 2: tz_hh_mm_ss: /* +hh:mm:ss */
2015 DO_TZ_OFFSET (9, 024,
2016 hour_diff * 10000 + min_diff * 100 + sec_diff);
2018 case 3: /* +hh if possible, else +hh:mm, else +hh:mm:ss */
2019 if (sec_diff != 0)
2020 goto tz_hh_mm_ss;
2021 if (min_diff != 0)
2022 goto tz_hh_mm;
2023 DO_TZ_OFFSET (3, 0, hour_diff);
2025 default:
2026 goto bad_format;
2030 case L_('\0'): /* GNU extension: % at end of format. */
2031 bad_percent:
2032 --f;
2033 FALLTHROUGH;
2034 default:
2035 /* Unknown format; output the format, including the '%',
2036 since this is most likely the right thing to do if a
2037 multibyte string has been misparsed. */
2038 bad_format:
2039 cpy (f - percent + 1, percent);
2040 break;
2044 #if ! FPRINTFTIME
2045 if (p && maxsize != 0)
2046 *p = L_('\0');
2047 #endif
2049 errno = saved_errno;
2050 return i;