1 /* Copyright (C) 1991,92,93,94,95,96,97,98 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library 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 GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
23 /* Some hosts need this in order to declare localtime_r properly. */
24 #ifndef __EXTENSIONS__
25 # define __EXTENSIONS__ 1
29 # define HAVE_LIMITS_H 1
31 # define HAVE_MBRLEN 1
32 # define HAVE_STRUCT_ERA_ENTRY 1
33 # define HAVE_TM_GMTOFF 1
34 # define HAVE_TM_ZONE 1
35 # define HAVE_TZNAME 1
37 # define MULTIBYTE_IS_FORMAT_SAFE 1
38 # define STDC_HEADERS 1
39 # include "../locale/localeinfo.h"
42 #if defined emacs && !defined HAVE_BCOPY
43 # define HAVE_MEMCPY 1
47 #include <sys/types.h> /* Some systems define `time_t' here. */
49 /* Some systems require <unistd.h> to be included before <time.h>
50 for localtime_r to be declared properly. */
55 #ifdef TIME_WITH_SYS_TIME
56 # include <sys/time.h>
59 # ifdef HAVE_SYS_TIME_H
60 # include <sys/time.h>
66 extern char *tzname
[];
69 /* Do multibyte processing if multibytes are supported, unless
70 multibyte sequences are safe in formats. Multibyte sequences are
71 safe if they cannot contain byte sequences that look like format
72 conversion specifications. The GNU C Library uses UTF8 multibyte
73 encoding, which is safe for formats, but strftime.c can be used
74 with other C libraries that use unsafe encodings. */
75 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
81 /* Simulate mbrlen with mblen as best we can. */
82 # define mbstate_t int
83 # define mbrlen(s, n, ps) mblen (s, n)
84 # define mbsinit(ps) (*(ps) == 0)
86 static const mbstate_t mbstate_zero
;
99 # define memcpy(d, s, n) bcopy ((s), (d), (n))
104 # define MEMPCPY(d, s, n) __mempcpy (d, s, n)
106 # ifndef HAVE_MEMPCPY
107 # define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
112 # if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
113 # define __P(args) args
115 # define __P(args) ()
117 #endif /* Not __P. */
135 #define TYPE_SIGNED(t) ((t) -1 < 0)
137 /* Bound on length of the string representing an integer value of type t.
138 Subtract one for the sign bit if t is signed;
139 302 / 1000 is log10 (2) rounded up;
140 add one for integer division truncation;
141 add one more for a minus sign if t is signed. */
142 #define INT_STRLEN_BOUND(t) \
143 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
145 #define TM_YEAR_BASE 1900
148 /* Nonzero if YEAR is a leap year (every 4 years,
149 except every 100th isn't, and every 400th is). */
150 # define __isleap(year) \
151 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
156 # define gmtime_r __gmtime_r
157 # define localtime_r __localtime_r
158 # define tzname __tzname
159 # define tzset __tzset
161 # if ! HAVE_LOCALTIME_R
162 # if ! HAVE_TM_GMTOFF
163 /* Approximate gmtime_r as best we can in its absence. */
165 # define gmtime_r my_gmtime_r
166 static struct tm
*gmtime_r
__P ((const time_t *, struct tm
*));
172 struct tm
*l
= gmtime (t
);
178 # endif /* ! HAVE_TM_GMTOFF */
180 /* Approximate localtime_r as best we can in its absence. */
182 # define localtime_r my_ftime_localtime_r
183 static struct tm
*localtime_r
__P ((const time_t *, struct tm
*));
189 struct tm
*l
= localtime (t
);
195 # endif /* ! HAVE_LOCALTIME_R */
196 #endif /* ! defined _LIBC */
199 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
200 /* Some systems lack the `memset' function and we don't want to
201 introduce additional dependencies. */
202 /* The SGI compiler reportedly barfs on the trailing null
203 if we use a string constant as the initializer. 28 June 1997, rms. */
204 static const char spaces
[16] = /* " " */
205 { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ' };
206 static const char zeroes
[16] = /* "0000000000000000" */
207 { '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0' };
209 # define memset_space(P, Len) \
215 int _this = _len > 16 ? 16 : _len; \
216 (P) = MEMPCPY ((P), spaces, _this); \
222 # define memset_zero(P, Len) \
228 int _this = _len > 16 ? 16 : _len; \
229 (P) = MEMPCPY ((P), zeroes, _this); \
235 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
236 # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
243 int _delta = width - _n; \
244 int _incr = _n + (_delta > 0 ? _delta : 0); \
245 if (i + _incr >= maxsize) \
252 memset_zero (p, _delta); \
254 memset_space (p, _delta); \
265 memcpy_lowcase (p, (s), _n); \
266 else if (to_uppcase) \
267 memcpy_uppcase (p, (s), _n); \
269 memcpy ((PTR) p, (PTR) (s), _n))
274 # define TOUPPER(Ch) toupper (Ch)
275 # define TOLOWER(Ch) tolower (Ch)
277 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
278 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
280 /* We don't use `isdigit' here since the locale dependent
281 interpretation is not what we want here. We only need to accept
282 the arabic digits in the ASCII range. One day there is perhaps a
283 more reliable way to accept other sets of digits. */
284 #define ISDIGIT(Ch) ((unsigned int) (Ch) - '0' <= 9)
286 static char *memcpy_lowcase
__P ((char *dest
, const char *src
, size_t len
));
289 memcpy_lowcase (dest
, src
, len
)
295 dest
[len
] = TOLOWER ((unsigned char) src
[len
]);
299 static char *memcpy_uppcase
__P ((char *dest
, const char *src
, size_t len
));
302 memcpy_uppcase (dest
, src
, len
)
308 dest
[len
] = TOUPPER ((unsigned char) src
[len
]);
314 /* Yield the difference between *A and *B,
315 measured in seconds, ignoring leap seconds. */
316 # define tm_diff ftime_tm_diff
317 static int tm_diff
__P ((const struct tm
*, const struct tm
*));
323 /* Compute intervening leap days correctly even if year is negative.
324 Take care to avoid int overflow in leap day calculations,
325 but it's OK to assume that A and B are close to each other. */
326 int a4
= (a
->tm_year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (a
->tm_year
& 3);
327 int b4
= (b
->tm_year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (b
->tm_year
& 3);
328 int a100
= a4
/ 25 - (a4
% 25 < 0);
329 int b100
= b4
/ 25 - (b4
% 25 < 0);
330 int a400
= a100
>> 2;
331 int b400
= b100
>> 2;
332 int intervening_leap_days
= (a4
- b4
) - (a100
- b100
) + (a400
- b400
);
333 int years
= a
->tm_year
- b
->tm_year
;
334 int days
= (365 * years
+ intervening_leap_days
335 + (a
->tm_yday
- b
->tm_yday
));
336 return (60 * (60 * (24 * days
+ (a
->tm_hour
- b
->tm_hour
))
337 + (a
->tm_min
- b
->tm_min
))
338 + (a
->tm_sec
- b
->tm_sec
));
340 #endif /* ! HAVE_TM_GMTOFF */
344 /* The number of days from the first day of the first ISO week of this
345 year to the year day YDAY with week day WDAY. ISO weeks start on
346 Monday; the first ISO week has the year's first Thursday. YDAY may
347 be as small as YDAY_MINIMUM. */
348 #define ISO_WEEK_START_WDAY 1 /* Monday */
349 #define ISO_WEEK1_WDAY 4 /* Thursday */
350 #define YDAY_MINIMUM (-366)
351 static int iso_week_days
__P ((int, int));
356 iso_week_days (yday
, wday
)
360 /* Add enough to the first operand of % to make it nonnegative. */
361 int big_enough_multiple_of_7
= (-YDAY_MINIMUM
/ 7 + 2) * 7;
363 - (yday
- wday
+ ISO_WEEK1_WDAY
+ big_enough_multiple_of_7
) % 7
364 + ISO_WEEK1_WDAY
- ISO_WEEK_START_WDAY
);
368 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
369 static char const weekday_name
[][10] =
371 "Sunday", "Monday", "Tuesday", "Wednesday",
372 "Thursday", "Friday", "Saturday"
374 static char const month_name
[][10] =
376 "January", "February", "March", "April", "May", "June",
377 "July", "August", "September", "October", "November", "December"
383 # define my_strftime emacs_strftimeu
384 # define ut_argument , ut
385 # define ut_argument_spec int ut;
386 # define ut_argument_spec_iso , int ut
388 # define my_strftime strftime
390 # define ut_argument_spec
391 # define ut_argument_spec_iso
392 /* We don't have this information in general. */
396 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
397 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
398 Work around this bug by copying *tp before it might be munged. */
399 size_t _strftime_copytm
__P ((char *, size_t, const char *,
400 const struct tm
* ut_argument_spec_iso
));
402 my_strftime (s
, maxsize
, format
, tp ut_argument
)
411 return _strftime_copytm (s
, maxsize
, format
, &tmcopy ut_argument
);
414 # define my_strftime(S, Maxsize, Format, Tp) \
415 _strftime_copytm (S, Maxsize, Format, Tp)
419 /* Write information from TP into S according to the format
420 string FORMAT, writing no more that MAXSIZE characters
421 (including the terminating '\0') and returning number of
422 characters written. If S is NULL, nothing will be written
423 anywhere, so to determine how many characters would be
424 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
426 my_strftime (s
, maxsize
, format
, tp ut_argument
)
433 int hour12
= tp
->tm_hour
;
435 /* We cannot make the following values variables since we must delay
436 the evaluation of these values until really needed since some
437 expressions might not be valid in every situation. The `struct tm'
438 might be generated by a strptime() call that initialized
439 only a few elements. Dereference the pointers only if the format
440 requires this. Then it is ok to fail if the pointers are invalid. */
441 # define a_wkday _NL_CURRENT (LC_TIME, ABDAY_1 + tp->tm_wday)
442 # define f_wkday _NL_CURRENT (LC_TIME, DAY_1 + tp->tm_wday)
443 # define a_month _NL_CURRENT (LC_TIME, ABMON_1 + tp->tm_mon)
444 # define f_month _NL_CURRENT (LC_TIME, MON_1 + tp->tm_mon)
445 # define ampm _NL_CURRENT (LC_TIME, tp->tm_hour > 11 ? PM_STR : AM_STR)
447 # define aw_len strlen (a_wkday)
448 # define am_len strlen (a_month)
449 # define ap_len strlen (ampm)
452 # define f_wkday (weekday_name[tp->tm_wday])
453 # define f_month (month_name[tp->tm_mon])
454 # define a_wkday f_wkday
455 # define a_month f_month
456 # define ampm ("AMPM" + 2 * (tp->tm_hour > 11))
470 /* The POSIX test suite assumes that setting
471 the environment variable TZ to a new value before calling strftime()
472 will influence the result (the %Z format) even if the information in
473 TP is computed with a totally different time zone.
474 This is bogus: though POSIX allows bad behavior like this,
475 POSIX does not require it. Do the right thing instead. */
476 zone
= (const char *) tp
->tm_zone
;
481 if (! (zone
&& *zone
))
486 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
487 time zone names contained in the external variable `tzname' shall
488 be set as if the tzset() function had been called. */
501 for (f
= format
; *f
!= '\0'; ++f
)
503 int pad
= 0; /* Padding for number ('-', '_', or 0). */
504 int modifier
; /* Field modifier ('E', 'O', or 0). */
505 int digits
; /* Max digits for numeric format. */
506 int number_value
; /* Numeric value to be printed. */
507 int negative_number
; /* 1 if the number is negative. */
510 char buf
[1 + (sizeof (int) < sizeof (time_t)
511 ? INT_STRLEN_BOUND (time_t)
512 : INT_STRLEN_BOUND (int))];
526 case '\a': case '\b': case '\t': case '\n':
527 case '\v': case '\f': case '\r':
528 case ' ': case '!': case '"': case '#': case '&': case'\'':
529 case '(': case ')': case '*': case '+': case ',': case '-':
530 case '.': case '/': case '0': case '1': case '2': case '3':
531 case '4': case '5': case '6': case '7': case '8': case '9':
532 case ':': case ';': case '<': case '=': case '>': case '?':
533 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
534 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
535 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
536 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
537 case 'Y': case 'Z': case '[': case'\\': case ']': case '^':
538 case '_': case 'a': case 'b': case 'c': case 'd': case 'e':
539 case 'f': case 'g': case 'h': case 'i': case 'j': case 'k':
540 case 'l': case 'm': case 'n': case 'o': case 'p': case 'q':
541 case 'r': case 's': case 't': case 'u': case 'v': case 'w':
542 case 'x': case 'y': case 'z': case '{': case '|': case '}':
544 /* The C Standard requires these 98 characters (plus '%') to
545 be in the basic execution character set. None of these
546 characters can start a multibyte sequence, so they need
547 not be analyzed further. */
552 /* Copy this multibyte sequence until we reach its end, find
553 an error, or come back to the initial shift state. */
555 mbstate_t mbstate
= mbstate_zero
;
560 size_t bytes
= mbrlen (f
+ len
, (size_t) -1, &mbstate
);
565 if (bytes
== (size_t) -2)
567 len
+= strlen (f
+ len
);
571 if (bytes
== (size_t) -1)
579 while (! mbsinit (&mbstate
));
587 #else /* ! DO_MULTIBYTE */
589 /* Either multibyte encodings are not supported, or they are
590 safe for formats, so any non-'%' byte can be copied through. */
597 #endif /* ! DO_MULTIBYTE */
599 /* Check for flags that can modify a format. */
604 /* This influences the number formats. */
611 /* This changes textual output. */
625 /* As a GNU extension we allow to specify the field width. */
635 while (ISDIGIT (*f
));
638 /* Check for modifiers. */
651 /* Now do the specified format. */
655 #define DO_NUMBER(d, v) \
656 digits = width == -1 ? d : width; \
657 number_value = v; goto do_number
658 #define DO_NUMBER_SPACEPAD(d, v) \
659 digits = width == -1 ? d : width; \
660 number_value = v; goto do_number_spacepad
676 #if defined _NL_CURRENT || !HAVE_STRFTIME
677 cpy (aw_len
, a_wkday
);
680 goto underlying_strftime
;
691 #if defined _NL_CURRENT || !HAVE_STRFTIME
692 cpy (strlen (f_wkday
), f_wkday
);
695 goto underlying_strftime
;
699 case 'h': /* POSIX.2 extension. */
702 #if defined _NL_CURRENT || !HAVE_STRFTIME
703 cpy (am_len
, a_month
);
706 goto underlying_strftime
;
717 #if defined _NL_CURRENT || !HAVE_STRFTIME
718 cpy (strlen (f_month
), f_month
);
721 goto underlying_strftime
;
728 if (! (modifier
== 'E'
729 && *(subfmt
= _NL_CURRENT (LC_TIME
, ERA_D_T_FMT
)) != '\0'))
730 subfmt
= _NL_CURRENT (LC_TIME
, D_T_FMT
);
733 goto underlying_strftime
;
735 subfmt
= "%a %b %e %H:%M:%S %Y";
742 size_t len
= my_strftime (NULL
, (size_t) -1, subfmt
, tp
);
743 add (len
, my_strftime (p
, maxsize
- i
, subfmt
, tp
));
746 while (old_start
< p
)
748 *old_start
= TOUPPER ((unsigned char) *old_start
);
754 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
757 /* The relevant information is available only via the
758 underlying strftime implementation, so use that. */
761 char ubuf
[1024]; /* enough for any single format in practice */
768 len
= strftime (ubuf
, sizeof ubuf
, ufmt
, tp
);
769 if (len
== 0 && ubuf
[0] != '\0')
776 case 'C': /* POSIX.2 extension. */
781 #if HAVE_STRUCT_ERA_ENTRY
782 struct era_entry
*era
= _nl_get_era_entry (tp
);
785 size_t len
= strlen (era
->name_fmt
);
786 cpy (len
, era
->name_fmt
);
791 goto underlying_strftime
;
797 int year
= tp
->tm_year
+ TM_YEAR_BASE
;
798 DO_NUMBER (1, year
/ 100 - (year
% 100 < 0));
805 if (! (modifier
== 'E'
806 && *(subfmt
= _NL_CURRENT (LC_TIME
, ERA_D_FMT
)) != '\0'))
807 subfmt
= _NL_CURRENT (LC_TIME
, D_FMT
);
811 goto underlying_strftime
;
816 case 'D': /* POSIX.2 extension. */
826 DO_NUMBER (2, tp
->tm_mday
);
828 case 'e': /* POSIX.2 extension. */
832 DO_NUMBER_SPACEPAD (2, tp
->tm_mday
);
834 /* All numeric formats set DIGITS and NUMBER_VALUE and then
835 jump to one of these two labels. */
838 /* Force `_' flag unless overwritten by `0' flag. */
843 /* Format the number according to the MODIFIER flag. */
845 if (modifier
== 'O' && 0 <= number_value
)
848 /* Get the locale specific alternate representation of
849 the number NUMBER_VALUE. If none exist NULL is returned. */
850 const char *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
);
871 negative_number
= number_value
< 0;
877 *--bufp
= u
% 10 + '0';
878 while ((u
/= 10) != 0);
881 do_number_sign_and_padding
:
887 int padding
= digits
- (buf
+ sizeof (buf
) - bufp
);
891 while (0 < padding
--)
896 bufp
+= negative_number
;
897 while (0 < padding
--)
904 cpy (buf
+ sizeof (buf
) - bufp
, bufp
);
917 DO_NUMBER (2, tp
->tm_hour
);
923 DO_NUMBER (2, hour12
);
925 case 'k': /* GNU extension. */
929 DO_NUMBER_SPACEPAD (2, tp
->tm_hour
);
931 case 'l': /* GNU extension. */
935 DO_NUMBER_SPACEPAD (2, hour12
);
941 DO_NUMBER (3, 1 + tp
->tm_yday
);
947 DO_NUMBER (2, tp
->tm_min
);
953 DO_NUMBER (2, tp
->tm_mon
+ 1);
955 case 'n': /* POSIX.2 extension. */
961 #if !defined _NL_CURRENT && HAVE_STRFTIME
972 #if defined _NL_CURRENT || !HAVE_STRFTIME
976 goto underlying_strftime
;
979 case 'R': /* GNU extension. */
983 case 'r': /* POSIX.2 extension. */
985 if (*(subfmt
= _NL_CURRENT (LC_TIME
, T_FMT_AMPM
)) == '\0')
987 subfmt
= "%I:%M:%S %p";
994 DO_NUMBER (2, tp
->tm_sec
);
996 case 's': /* GNU extension. */
1004 /* Generate string value for T using time_t arithmetic;
1005 this works even if sizeof (long) < sizeof (time_t). */
1007 bufp
= buf
+ sizeof (buf
);
1008 negative_number
= t
< 0;
1015 if (negative_number
)
1019 /* Adjust if division truncates to minus infinity. */
1020 if (0 < -1 % 10 && d
< 0)
1032 goto do_number_sign_and_padding
;
1036 if (modifier
== 'O')
1039 if (! (modifier
== 'E'
1040 && *(subfmt
= _NL_CURRENT (LC_TIME
, ERA_T_FMT
)) != '\0'))
1041 subfmt
= _NL_CURRENT (LC_TIME
, T_FMT
);
1045 goto underlying_strftime
;
1050 case 'T': /* POSIX.2 extension. */
1051 subfmt
= "%H:%M:%S";
1054 case 't': /* POSIX.2 extension. */
1059 case 'u': /* POSIX.2 extension. */
1060 DO_NUMBER (1, (tp
->tm_wday
- 1 + 7) % 7 + 1);
1063 if (modifier
== 'E')
1066 DO_NUMBER (2, (tp
->tm_yday
- tp
->tm_wday
+ 7) / 7);
1069 case 'g': /* GNU extension. */
1070 case 'G': /* GNU extension. */
1071 if (modifier
== 'E')
1074 int year
= tp
->tm_year
+ TM_YEAR_BASE
;
1075 int days
= iso_week_days (tp
->tm_yday
, tp
->tm_wday
);
1079 /* This ISO week belongs to the previous year. */
1081 days
= iso_week_days (tp
->tm_yday
+ (365 + __isleap (year
)),
1086 int d
= iso_week_days (tp
->tm_yday
- (365 + __isleap (year
)),
1090 /* This ISO week belongs to the next year. */
1099 DO_NUMBER (2, (year
% 100 + 100) % 100);
1102 DO_NUMBER (1, year
);
1105 DO_NUMBER (2, days
/ 7 + 1);
1110 if (modifier
== 'E')
1113 DO_NUMBER (2, (tp
->tm_yday
- (tp
->tm_wday
- 1 + 7) % 7 + 7) / 7);
1116 if (modifier
== 'E')
1119 DO_NUMBER (1, tp
->tm_wday
);
1122 if (modifier
== 'E')
1124 #if HAVE_STRUCT_ERA_ENTRY
1125 struct era_entry
*era
= _nl_get_era_entry (tp
);
1128 subfmt
= strchr (era
->name_fmt
, '\0') + 1;
1133 goto underlying_strftime
;
1137 if (modifier
== 'O')
1140 DO_NUMBER (1, tp
->tm_year
+ TM_YEAR_BASE
);
1143 if (modifier
== 'E')
1145 #if HAVE_STRUCT_ERA_ENTRY
1146 struct era_entry
*era
= _nl_get_era_entry (tp
);
1149 int delta
= tp
->tm_year
- era
->start_date
[0];
1150 DO_NUMBER (1, (era
->offset
1151 + (era
->direction
== '-' ? -delta
: delta
)));
1155 goto underlying_strftime
;
1159 DO_NUMBER (2, (tp
->tm_year
% 100 + 100) % 100);
1169 /* The tzset() call might have changed the value. */
1170 if (!(zone
&& *zone
) && tp
->tm_isdst
>= 0)
1171 zone
= tzname
[tp
->tm_isdst
];
1174 zone
= ""; /* POSIX.2 requires the empty string here. */
1176 cpy (strlen (zone
), zone
);
1179 case 'z': /* GNU extension. */
1180 if (tp
->tm_isdst
< 0)
1186 diff
= tp
->tm_gmtoff
;
1199 if (lt
== (time_t) -1)
1201 /* mktime returns -1 for errors, but -1 is also a
1202 valid time_t value. Check whether an error really
1206 if (! localtime_r (<
, &tm
)
1207 || ((ltm
.tm_sec
^ tm
.tm_sec
)
1208 | (ltm
.tm_min
^ tm
.tm_min
)
1209 | (ltm
.tm_hour
^ tm
.tm_hour
)
1210 | (ltm
.tm_mday
^ tm
.tm_mday
)
1211 | (ltm
.tm_mon
^ tm
.tm_mon
)
1212 | (ltm
.tm_year
^ tm
.tm_year
)))
1216 if (! gmtime_r (<
, >m
))
1219 diff
= tm_diff (<m
, >m
);
1232 DO_NUMBER (4, (diff
/ 60) * 100 + diff
% 60);
1235 case '\0': /* GNU extension: % at end of format. */
1239 /* Unknown format; output the format, including the '%',
1240 since this is most likely the right thing to do if a
1241 multibyte string has been misparsed. */
1245 for (flen
= 1; f
[1 - flen
] != '%'; flen
++)
1247 cpy (flen
, &f
[1 - flen
]);
1253 if (p
&& i
< maxsize
)
1260 /* For Emacs we have a separate interface which corresponds to the normal
1261 strftime function and does not have the extra information whether the
1262 TP arguments comes from a `gmtime' call or not. */
1264 emacs_strftime (s
, maxsize
, format
, tp
)
1268 const struct tm
*tp
;
1270 return my_strftime (s
, maxsize
, format
, tp
, 0);