1 /* Copyright (C) 1991-1999, 2000, 2001, 2003 Free Software Foundation, Inc.
3 NOTE: The canonical source of this file is maintained with the GNU C Library.
4 Bugs can be reported to bug-glibc@prep.ai.mit.edu.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
26 # define HAVE_MBRLEN 1
27 # define HAVE_STRUCT_ERA_ENTRY 1
28 # define HAVE_TM_GMTOFF 1
29 # define HAVE_TM_ZONE 1
30 # define HAVE_TZNAME 1
32 # define MULTIBYTE_IS_FORMAT_SAFE 1
33 # include "../locale/localeinfo.h"
37 #include <sys/types.h> /* Some systems define `time_t' here. */
39 #ifdef TIME_WITH_SYS_TIME
40 # include <sys/time.h>
43 # ifdef HAVE_SYS_TIME_H
44 # include <sys/time.h>
50 extern char *tzname[];
53 /* Do multibyte processing if multibytes are supported, unless
54 multibyte sequences are safe in formats. Multibyte sequences are
55 safe if they cannot contain byte sequences that look like format
56 conversion specifications. The GNU C Library uses UTF8 multibyte
57 encoding, which is safe for formats, but strftime.c can be used
58 with other C libraries that use unsafe encodings. */
59 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
65 /* Simulate mbrlen with mblen as best we can. */
66 # define mbstate_t int
67 # define mbrlen(s, n, ps) mblen (s, n)
68 # define mbsinit(ps) (*(ps) == 0)
70 static const mbstate_t mbstate_zero;
80 # define CHAR_T wchar_t
81 # define UCHAR_T unsigned int
82 # define L_(Str) L##Str
83 # define NLW(Sym) _NL_W##Sym
85 # define MEMCPY(d, s, n) __wmemcpy (d, s, n)
86 # define STRLEN(s) __wcslen (s)
90 # define UCHAR_T unsigned char
94 # define MEMCPY(d, s, n) memcpy (d, s, n)
95 # define STRLEN(s) strlen (s)
98 # define MEMPCPY(d, s, n) __mempcpy (d, s, n)
100 # ifndef HAVE_MEMPCPY
101 # define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
106 #define TYPE_SIGNED(t) ((t) -1 < 0)
108 /* Bound on length of the string representing an integer value of type t.
109 Subtract one for the sign bit if t is signed;
110 302 / 1000 is log10 (2) rounded up;
111 add one for integer division truncation;
112 add one more for a minus sign if t is signed. */
113 #define INT_STRLEN_BOUND(t) \
114 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
116 #define TM_YEAR_BASE 1900
119 /* Nonzero if YEAR is a leap year (every 4 years,
120 except every 100th isn't, and every 400th is). */
121 # define __isleap(year) \
122 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
127 # define tzname __tzname
128 # define tzset __tzset
132 /* Portable standalone applications should supply a "time_r.h" that
133 declares a POSIX-compliant localtime_r, for the benefit of older
134 implementations that lack localtime_r or have a nonstandard one.
135 See the gnulib time_r module for one way to implement this. */
138 # undef __localtime_r
139 # define __gmtime_r gmtime_r
140 # define __localtime_r localtime_r
145 # define memset_space(P, Len) (wmemset (P, L' ', Len), (P) += (Len))
146 # define memset_zero(P, Len) (wmemset (P, L'0', Len), (P) += (Len))
148 # define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len))
149 # define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len))
156 int _delta = width - _n; \
157 int _incr = _n + (_delta > 0 ? _delta : 0); \
158 if ((size_t) _incr >= maxsize - i) \
164 if (pad == L_('0')) \
165 memset_zero (p, _delta); \
167 memset_space (p, _delta); \
178 memcpy_lowcase (p, (s), _n LOCALE_ARG); \
179 else if (to_uppcase) \
180 memcpy_uppcase (p, (s), _n LOCALE_ARG); \
182 MEMCPY ((void *) p, (void const *) (s), _n))
185 # ifndef USE_IN_EXTENDED_LOCALE_MODEL
186 # undef __mbsrtowcs_l
187 # define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
189 # define widen(os, ws, l) \
192 const char *__s = os; \
193 memset (&__st, '\0', sizeof (__st)); \
194 l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \
195 ws = (wchar_t *) alloca ((l + 1) * sizeof (wchar_t)); \
196 (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \
201 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
202 /* We use this code also for the extended locale handling where the
203 function gets as an additional argument the locale which has to be
204 used. To access the values we have to redefine the _NL_CURRENT
206 # define strftime __strftime_l
207 # define wcsftime __wcsftime_l
209 # define _NL_CURRENT(category, item) \
210 (current->values[_NL_ITEM_INDEX (item)].string)
211 # define LOCALE_ARG , loc
212 # define LOCALE_PARAM_PROTO , __locale_t loc
213 # define HELPER_LOCALE_ARG , current
215 # define LOCALE_PARAM_PROTO
218 # define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
220 # define HELPER_LOCALE_ARG
225 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
226 # define TOUPPER(Ch, L) __towupper_l (Ch, L)
227 # define TOLOWER(Ch, L) __towlower_l (Ch, L)
229 # define TOUPPER(Ch, L) towupper (Ch)
230 # define TOLOWER(Ch, L) towlower (Ch)
234 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
235 # define TOUPPER(Ch, L) __toupper_l (Ch, L)
236 # define TOLOWER(Ch, L) __tolower_l (Ch, L)
238 # define TOUPPER(Ch, L) toupper (Ch)
239 # define TOLOWER(Ch, L) tolower (Ch)
242 # define TOUPPER(Ch, L) (islower (Ch) ? toupper (Ch) : (Ch))
243 # define TOLOWER(Ch, L) (isupper (Ch) ? tolower (Ch) : (Ch))
246 /* We don't use `isdigit' here since the locale dependent
247 interpretation is not what we want here. We only need to accept
248 the arabic digits in the ASCII range. One day there is perhaps a
249 more reliable way to accept other sets of digits. */
250 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
253 memcpy_lowcase (CHAR_T *dest, const CHAR_T *src,
254 size_t len LOCALE_PARAM_PROTO)
257 dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
262 memcpy_uppcase (CHAR_T *dest, const CHAR_T *src,
263 size_t len LOCALE_PARAM_PROTO)
266 dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
272 /* Yield the difference between *A and *B,
273 measured in seconds, ignoring leap seconds. */
274 # define tm_diff ftime_tm_diff
276 tm_diff (const struct tm *a, const struct tm *b)
278 /* Compute intervening leap days correctly even if year is negative.
279 Take care to avoid int overflow in leap day calculations,
280 but it's OK to assume that A and B are close to each other. */
281 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
282 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
283 int a100 = a4 / 25 - (a4 % 25 < 0);
284 int b100 = b4 / 25 - (b4 % 25 < 0);
285 int a400 = a100 >> 2;
286 int b400 = b100 >> 2;
287 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
288 int years = a->tm_year - b->tm_year;
289 int days = (365 * years + intervening_leap_days
290 + (a->tm_yday - b->tm_yday));
291 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
292 + (a->tm_min - b->tm_min))
293 + (a->tm_sec - b->tm_sec));
295 #endif /* ! HAVE_TM_GMTOFF */
299 /* The number of days from the first day of the first ISO week of this
300 year to the year day YDAY with week day WDAY. ISO weeks start on
301 Monday; the first ISO week has the year's first Thursday. YDAY may
302 be as small as YDAY_MINIMUM. */
303 #define ISO_WEEK_START_WDAY 1 /* Monday */
304 #define ISO_WEEK1_WDAY 4 /* Thursday */
305 #define YDAY_MINIMUM (-366)
310 iso_week_days (int yday, int wday)
312 /* Add enough to the first operand of % to make it nonnegative. */
313 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
315 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
316 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
320 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
321 static CHAR_T const weekday_name[][10] =
323 L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
324 L_("Thursday"), L_("Friday"), L_("Saturday")
326 static CHAR_T const month_name[][10] =
328 L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
329 L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
330 L_("November"), L_("December")
335 /* When compiling this file, GNU applications can #define my_strftime
336 to a symbol (typically nstrftime) to get an extended strftime with
337 extra arguments UT and NS. Emacs is a special case for now, but
338 this Emacs-specific code can be removed once Emacs's config.h
339 defines my_strftime. */
340 #if defined emacs && !defined my_strftime
341 # define my_strftime nstrftime
345 # define extra_args , ut, ns
346 # define extra_args_spec , int ut, int ns
349 # define my_strftime wcsftime
350 # define nl_get_alt_digit _nl_get_walt_digit
352 # define my_strftime strftime
353 # define nl_get_alt_digit _nl_get_alt_digit
356 # define extra_args_spec
357 /* We don't have this information in general. */
362 #if ! defined _LIBC && ! HAVE_RUN_TZSET_TEST
363 /* Solaris 2.5.x and 2.6 tzset sometimes modify the storage returned
364 by localtime. On such systems, we must use the tzset and localtime
365 wrappers to work around the bug. */
366 "you must run the autoconf test for a working tzset function"
370 /* Write information from TP into S according to the format
371 string FORMAT, writing no more that MAXSIZE characters
372 (including the terminating '\0') and returning number of
373 characters written. If S is NULL, nothing will be written
374 anywhere, so to determine how many characters would be
375 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
377 my_strftime (CHAR_T *s, size_t maxsize, const CHAR_T *format,
378 const struct tm *tp extra_args_spec LOCALE_PARAM_PROTO)
380 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
381 struct locale_data *const current = loc->__locales[LC_TIME];
384 int hour12 = tp->tm_hour;
386 /* We cannot make the following values variables since we must delay
387 the evaluation of these values until really needed since some
388 expressions might not be valid in every situation. The `struct tm'
389 might be generated by a strptime() call that initialized
390 only a few elements. Dereference the pointers only if the format
391 requires this. Then it is ok to fail if the pointers are invalid. */
393 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
395 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
397 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
399 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
401 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
402 ? NLW(PM_STR) : NLW(AM_STR)))
404 # define aw_len STRLEN (a_wkday)
405 # define am_len STRLEN (a_month)
406 # define ap_len STRLEN (ampm)
409 # define f_wkday (weekday_name[tp->tm_wday])
410 # define f_month (month_name[tp->tm_mon])
411 # define a_wkday f_wkday
412 # define a_month f_month
413 # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
424 #if DO_MULTIBYTE && !defined COMPILE_WIDE
425 const char *format_end = NULL;
430 /* The POSIX test suite assumes that setting
431 the environment variable TZ to a new value before calling strftime()
432 will influence the result (the %Z format) even if the information in
433 TP is computed with a totally different time zone.
434 This is bogus: though POSIX allows bad behavior like this,
435 POSIX does not require it. Do the right thing instead. */
436 zone = (const char *) tp->tm_zone;
441 if (! (zone && *zone))
446 /* POSIX.1 requires that local time zone information be used as
447 though strftime called tzset. */
460 for (f = format; *f != '\0'; ++f)
462 int pad = 0; /* Padding for number ('-', '_', or 0). */
463 int modifier; /* Field modifier ('E', 'O', or 0). */
464 int digits; /* Max digits for numeric format. */
465 int number_value; /* Numeric value to be printed. */
466 int negative_number; /* 1 if the number is negative. */
467 const CHAR_T *subfmt;
469 CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
470 ? INT_STRLEN_BOUND (time_t)
471 : INT_STRLEN_BOUND (int))];
478 #if DO_MULTIBYTE && !defined COMPILE_WIDE
484 case L_('\b'): case L_('\t'): case L_('\n'):
485 case L_('\v'): case L_('\f'): case L_('\r'):
486 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
487 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
488 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
489 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
490 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
491 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
492 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
493 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
494 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
495 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
496 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
497 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
498 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
499 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
500 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
501 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
502 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
503 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
505 /* The C Standard requires these 98 characters (plus '%') to
506 be in the basic execution character set. None of these
507 characters can start a multibyte sequence, so they need
508 not be analyzed further. */
513 /* Copy this multibyte sequence until we reach its end, find
514 an error, or come back to the initial shift state. */
516 mbstate_t mbstate = mbstate_zero;
521 format_end = f + strlen (f) + 1;
522 fsize = format_end - f;
526 size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
531 if (bytes == (size_t) -2)
533 len += strlen (f + len);
537 if (bytes == (size_t) -1)
545 while (! mbsinit (&mbstate));
553 #else /* ! DO_MULTIBYTE */
555 /* Either multibyte encodings are not supported, they are
556 safe for formats, so any non-'%' byte can be copied through,
557 or this is the wide character version. */
564 #endif /* ! DO_MULTIBYTE */
566 /* Check for flags that can modify a format. */
571 /* This influences the number formats. */
578 /* This changes textual output. */
592 /* As a GNU extension we allow to specify the field width. */
598 if (width > INT_MAX / 10
599 || (width == INT_MAX / 10 && *f - L_('0') > INT_MAX % 10))
600 /* Avoid overflow. */
605 width += *f - L_('0');
609 while (ISDIGIT (*f));
612 /* Check for modifiers. */
625 /* Now do the specified format. */
629 #define DO_NUMBER(d, v) \
630 digits = d > width ? d : width; \
631 number_value = v; goto do_number
632 #define DO_NUMBER_SPACEPAD(d, v) \
633 digits = d > width ? d : width; \
634 number_value = v; goto do_number_spacepad
650 #if defined _NL_CURRENT || !HAVE_STRFTIME
651 cpy (aw_len, a_wkday);
654 goto underlying_strftime;
665 #if defined _NL_CURRENT || !HAVE_STRFTIME
666 cpy (STRLEN (f_wkday), f_wkday);
669 goto underlying_strftime;
681 #if defined _NL_CURRENT || !HAVE_STRFTIME
682 cpy (am_len, a_month);
685 goto underlying_strftime;
696 #if defined _NL_CURRENT || !HAVE_STRFTIME
697 cpy (STRLEN (f_month), f_month);
700 goto underlying_strftime;
704 if (modifier == L_('O'))
707 if (! (modifier == 'E'
709 (const CHAR_T *) _NL_CURRENT (LC_TIME,
712 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
715 goto underlying_strftime;
717 subfmt = L_("%a %b %e %H:%M:%S %Y");
723 CHAR_T *old_start = p;
724 size_t len = my_strftime (NULL, (size_t) -1, subfmt,
725 tp extra_args LOCALE_ARG);
726 add (len, my_strftime (p, maxsize - i, subfmt,
727 tp extra_args LOCALE_ARG));
730 while (old_start < p)
732 *old_start = TOUPPER ((UCHAR_T) *old_start, loc);
738 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
741 /* The relevant information is available only via the
742 underlying strftime implementation, so use that. */
745 char ubuf[1024]; /* enough for any single format in practice */
747 /* Make sure we're calling the actual underlying strftime.
748 In some cases, config.h contains something like
749 "#define strftime rpl_strftime". */
760 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
761 if (len == 0 && ubuf[0] != '\0')
769 if (modifier == L_('O'))
771 if (modifier == L_('E'))
773 #if HAVE_STRUCT_ERA_ENTRY
774 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
778 size_t len = __wcslen (era->era_wname);
779 cpy (len, era->era_wname);
781 size_t len = strlen (era->era_name);
782 cpy (len, era->era_name);
788 goto underlying_strftime;
794 int year = tp->tm_year + TM_YEAR_BASE;
795 DO_NUMBER (1, year / 100 - (year % 100 < 0));
799 if (modifier == L_('O'))
802 if (! (modifier == L_('E')
804 (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
806 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
810 goto underlying_strftime;
818 subfmt = L_("%m/%d/%y");
822 if (modifier == L_('E'))
825 DO_NUMBER (2, tp->tm_mday);
828 if (modifier == L_('E'))
831 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
833 /* All numeric formats set DIGITS and NUMBER_VALUE and then
834 jump to one of these two labels. */
837 /* Force `_' flag unless overridden by `0' or `-' flag. */
838 if (pad != L_('0') && pad != L_('-'))
842 /* Format the number according to the MODIFIER flag. */
844 if (modifier == L_('O') && 0 <= number_value)
847 /* Get the locale specific alternate representation of
848 the number NUMBER_VALUE. If none exist NULL is returned. */
849 const CHAR_T *cp = nl_get_alt_digit (number_value
854 size_t digitlen = STRLEN (cp);
863 goto underlying_strftime;
868 unsigned int u = number_value;
870 bufp = buf + sizeof (buf) / sizeof (buf[0]);
871 negative_number = number_value < 0;
877 *--bufp = u % 10 + L_('0');
878 while ((u /= 10) != 0);
881 do_number_sign_and_padding:
887 int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
894 if ((size_t) padding >= maxsize - i)
898 memset_space (p, padding);
900 width = width > padding ? width - padding : 0;
904 if ((size_t) digits >= maxsize - i)
917 memset_zero (p, padding);
924 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
930 subfmt = L_("%Y-%m-%d");
934 if (modifier == L_('E'))
937 DO_NUMBER (2, tp->tm_hour);
940 if (modifier == L_('E'))
943 DO_NUMBER (2, hour12);
945 case L_('k'): /* GNU extension. */
946 if (modifier == L_('E'))
949 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
951 case L_('l'): /* GNU extension. */
952 if (modifier == L_('E'))
955 DO_NUMBER_SPACEPAD (2, hour12);
958 if (modifier == L_('E'))
961 DO_NUMBER (3, 1 + tp->tm_yday);
964 if (modifier == L_('E'))
967 DO_NUMBER (2, tp->tm_min);
970 if (modifier == L_('E'))
973 DO_NUMBER (2, tp->tm_mon + 1);
976 case L_('N'): /* GNU extension. */
977 if (modifier == L_('E'))
983 /* Take an explicit width less than 9 as a precision. */
985 for (j = width; j < 9; j++)
989 DO_NUMBER (9, number_value);
993 add (1, *p = L_('\n'));
998 #if !defined _NL_CURRENT && HAVE_STRFTIME
999 format_char = L_('p');
1009 #if defined _NL_CURRENT || !HAVE_STRFTIME
1013 goto underlying_strftime;
1017 subfmt = L_("%H:%M");
1021 #if !defined _NL_CURRENT && HAVE_STRFTIME
1022 goto underlying_strftime;
1025 if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1029 subfmt = L_("%I:%M:%S %p");
1034 if (modifier == L_('E'))
1037 DO_NUMBER (2, tp->tm_sec);
1039 case L_('s'): /* GNU extension. */
1047 /* Generate string value for T using time_t arithmetic;
1048 this works even if sizeof (long) < sizeof (time_t). */
1050 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1051 negative_number = t < 0;
1058 if (negative_number)
1062 /* Adjust if division truncates to minus infinity. */
1063 if (0 < -1 % 10 && d < 0)
1070 *--bufp = d + L_('0');
1075 goto do_number_sign_and_padding;
1079 if (modifier == L_('O'))
1082 if (! (modifier == L_('E')
1084 (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1086 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1090 goto underlying_strftime;
1096 subfmt = L_("%H:%M:%S");
1100 add (1, *p = L_('\t'));
1104 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1107 if (modifier == L_('E'))
1110 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1115 if (modifier == L_('E'))
1118 int year = tp->tm_year + TM_YEAR_BASE;
1119 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1123 /* This ISO week belongs to the previous year. */
1125 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1130 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1134 /* This ISO week belongs to the next year. */
1143 DO_NUMBER (2, (year % 100 + 100) % 100);
1146 DO_NUMBER (1, year);
1149 DO_NUMBER (2, days / 7 + 1);
1154 if (modifier == L_('E'))
1157 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1160 if (modifier == L_('E'))
1163 DO_NUMBER (1, tp->tm_wday);
1166 if (modifier == 'E')
1168 #if HAVE_STRUCT_ERA_ENTRY
1169 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1172 # ifdef COMPILE_WIDE
1173 subfmt = era->era_wformat;
1175 subfmt = era->era_format;
1181 goto underlying_strftime;
1185 if (modifier == L_('O'))
1188 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1191 if (modifier == L_('E'))
1193 #if HAVE_STRUCT_ERA_ENTRY
1194 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1197 int delta = tp->tm_year - era->start_date[0];
1198 DO_NUMBER (1, (era->offset
1199 + delta * era->absolute_direction));
1203 goto underlying_strftime;
1207 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1217 /* The tzset() call might have changed the value. */
1218 if (!(zone && *zone) && tp->tm_isdst >= 0)
1219 zone = tzname[tp->tm_isdst];
1226 /* The zone string is always given in multibyte form. We have
1227 to transform it first. */
1230 widen (zone, wczone, len);
1234 cpy (strlen (zone), zone);
1239 if (tp->tm_isdst < 0)
1245 diff = tp->tm_gmtoff;
1258 if (lt == (time_t) -1)
1260 /* mktime returns -1 for errors, but -1 is also a
1261 valid time_t value. Check whether an error really
1265 if (! __localtime_r (<, &tm)
1266 || ((ltm.tm_sec ^ tm.tm_sec)
1267 | (ltm.tm_min ^ tm.tm_min)
1268 | (ltm.tm_hour ^ tm.tm_hour)
1269 | (ltm.tm_mday ^ tm.tm_mday)
1270 | (ltm.tm_mon ^ tm.tm_mon)
1271 | (ltm.tm_year ^ tm.tm_year)))
1275 if (! __gmtime_r (<, >m))
1278 diff = tm_diff (<m, >m);
1284 add (1, *p = L_('-'));
1288 add (1, *p = L_('+'));
1291 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1294 case L_('\0'): /* GNU extension: % at end of format. */
1298 /* Unknown format; output the format, including the '%',
1299 since this is most likely the right thing to do if a
1300 multibyte string has been misparsed. */
1304 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1306 cpy (flen, &f[1 - flen]);
1312 if (p && maxsize != 0)
1317 libc_hidden_def (my_strftime)
1322 /* For Emacs we have a separate interface which corresponds to the normal
1323 strftime function plus the ut argument, but without the ns argument. */
1325 emacs_strftimeu (char *s, size_t maxsize, const char *format,
1326 const struct tm *tp, int ut)
1328 return my_strftime (s, maxsize, format, tp, ut, 0);