1 /* Copyright (C) 2002-2017 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 Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the 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 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
31 # define HAVE_LOCALTIME_R 0
32 # include "../locale/localeinfo.h"
36 #if ! HAVE_LOCALTIME_R && ! defined localtime_r
38 # define localtime_r __localtime_r
40 /* Approximate localtime_r as best we can in its absence. */
41 # define localtime_r my_localtime_r
42 static struct tm
*localtime_r (const time_t *, struct tm
*);
44 localtime_r (const time_t *t
, struct tm
*tp
)
46 struct tm
*l
= localtime (t
);
53 #endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
56 #define match_char(ch1, ch2) if (ch1 != ch2) return NULL
57 #if defined __GNUC__ && __GNUC__ >= 2
58 # define match_string(cs1, s2) \
59 ({ size_t len = strlen (cs1); \
60 int result = __strncasecmp_l ((cs1), (s2), len, locale) == 0; \
61 if (result) (s2) += len; \
64 /* Oh come on. Get a reasonable compiler. */
65 # define match_string(cs1, s2) \
66 (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
68 /* We intentionally do not use isdigit() for testing because this will
69 lead to problems with the wide character version. */
70 #define get_number(from, to, n) \
74 while (ISSPACE (*rp)) \
76 if (*rp < '0' || *rp > '9') \
81 } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9'); \
82 if (val < from || val > to) \
86 # define get_alt_number(from, to, n) \
88 __label__ do_normal; \
90 if (s.decided != raw) \
92 val = _nl_parse_alt_digit (&rp HELPER_LOCALE_ARG); \
93 if (val == -1 && s.decided != loc) \
98 if (val < from || val > to) \
104 get_number (from, to, n); \
109 # define get_alt_number(from, to, n) \
110 /* We don't have the alternate representation. */ \
111 get_number(from, to, n)
113 #define recursive(new_fmt) \
114 (*(new_fmt) != '\0' \
115 && (rp = __strptime_internal (rp, (new_fmt), tm, &s LOCALE_ARG)) != NULL)
119 /* This is defined in locale/C-time.c in the GNU libc. */
120 extern const struct __locale_data _nl_C_LC_TIME attribute_hidden
;
122 # define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
123 # define ab_weekday_name \
124 (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
125 # define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
126 # define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
127 # define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
128 # define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
129 # define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
130 # define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string)
131 # define HERE_T_FMT_AMPM \
132 (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string)
133 # define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string)
135 # define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n)
137 static char const weekday_name
[][10] =
139 "Sunday", "Monday", "Tuesday", "Wednesday",
140 "Thursday", "Friday", "Saturday"
142 static char const ab_weekday_name
[][4] =
144 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
146 static char const month_name
[][10] =
148 "January", "February", "March", "April", "May", "June",
149 "July", "August", "September", "October", "November", "December"
151 static char const ab_month_name
[][4] =
153 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
154 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
156 # define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
157 # define HERE_D_FMT "%m/%d/%y"
158 # define HERE_AM_STR "AM"
159 # define HERE_PM_STR "PM"
160 # define HERE_T_FMT_AMPM "%I:%M:%S %p"
161 # define HERE_T_FMT "%H:%M:%S"
163 static const unsigned short int __mon_yday
[2][13] =
166 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
168 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
173 /* We use this code also for the extended locale handling where the
174 function gets as an additional argument the locale which has to be
175 used. To access the values we have to redefine the _NL_CURRENT
177 # define strptime __strptime_l
179 # define _NL_CURRENT(category, item) \
180 (current->values[_NL_ITEM_INDEX (item)].string)
181 # undef _NL_CURRENT_WORD
182 # define _NL_CURRENT_WORD(category, item) \
183 (current->values[_NL_ITEM_INDEX (item)].word)
184 # define LOCALE_PARAM , locale_t locale
185 # define LOCALE_ARG , locale
186 # define HELPER_LOCALE_ARG , current
187 # define ISSPACE(Ch) __isspace_l (Ch, locale)
189 # define LOCALE_PARAM
191 # define HELPER_LOCALE_ARG
192 # define ISSPACE(Ch) isspace (Ch)
199 /* Nonzero if YEAR is a leap year (every 4 years,
200 except every 100th isn't, and every 400th is). */
201 # define __isleap(year) \
202 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
205 /* Compute the day of the week. */
207 day_of_the_week (struct tm
*tm
)
209 /* We know that January 1st 1970 was a Thursday (= 4). Compute the
210 difference between this data in the one on TM and so determine
212 int corr_year
= 1900 + tm
->tm_year
- (tm
->tm_mon
< 2);
214 + (365 * (tm
->tm_year
- 70))
216 - ((corr_year
/ 4) / 25) + ((corr_year
/ 4) % 25 < 0)
217 + (((corr_year
/ 4) / 25) / 4)
218 + __mon_yday
[0][tm
->tm_mon
]
220 tm
->tm_wday
= ((wday
% 7) + 7) % 7;
223 /* Compute the day of the year. */
225 day_of_the_year (struct tm
*tm
)
227 tm
->tm_yday
= (__mon_yday
[__isleap (1900 + tm
->tm_year
)][tm
->tm_mon
]
228 + (tm
->tm_mday
- 1));
237 __strptime_internal (const char *rp
, const char *fmt
, struct tm
*tmp
,
238 void *statep LOCALE_PARAM
)
241 struct __locale_data
*const current
= locale
->__locales
[LC_TIME
];
244 const char *rp_backup
;
245 const char *rp_longest
;
250 struct era_entry
*era
= NULL
;
251 enum ptime_locale_status
{ not, loc
, raw
} decided_longest
;
252 struct __strptime_state
254 unsigned int have_I
: 1;
255 unsigned int have_wday
: 1;
256 unsigned int have_yday
: 1;
257 unsigned int have_mon
: 1;
258 unsigned int have_mday
: 1;
259 unsigned int have_uweek
: 1;
260 unsigned int have_wweek
: 1;
261 unsigned int is_pm
: 1;
262 unsigned int want_century
: 1;
263 unsigned int want_era
: 1;
264 unsigned int want_xday
: 1;
265 enum ptime_locale_status decided
: 2;
275 memset (&s
, 0, sizeof (s
));
287 s
= *(struct __strptime_state
*) statep
;
294 /* A white space in the format string matches 0 more or white
295 space in the input string. */
298 while (ISSPACE (*rp
))
304 /* Any character but `%' must be matched by the same character
305 in the iput string. */
308 match_char (*fmt
++, *rp
++);
313 /* We discard strftime modifiers. */
314 while (*fmt
== '-' || *fmt
== '_' || *fmt
== '0'
315 || *fmt
== '^' || *fmt
== '#')
318 /* And field width. */
319 while (*fmt
>= '0' && *fmt
<= '9')
323 /* We need this for handling the `E' modifier. */
327 /* Make back up of current processing pointer. */
333 /* Match the `%' character itself. */
334 match_char ('%', *rp
++);
338 /* Match day of week. */
340 decided_longest
= s
.decided
;
342 for (cnt
= 0; cnt
< 7; ++cnt
)
349 if (match_string (_NL_CURRENT (LC_TIME
, DAY_1
+ cnt
), trp
)
355 && strcmp (_NL_CURRENT (LC_TIME
, DAY_1
+ cnt
),
357 decided_longest
= loc
;
360 if (match_string (_NL_CURRENT (LC_TIME
, ABDAY_1
+ cnt
), trp
)
366 && strcmp (_NL_CURRENT (LC_TIME
, ABDAY_1
+ cnt
),
367 ab_weekday_name
[cnt
]))
368 decided_longest
= loc
;
373 && (((trp
= rp
, match_string (weekday_name
[cnt
], trp
))
375 || ((trp
= rp
, match_string (ab_weekday_name
[cnt
], rp
))
376 && trp
> rp_longest
)))
380 decided_longest
= raw
;
383 if (rp_longest
== NULL
)
384 /* Does not match a weekday name. */
387 s
.decided
= decided_longest
;
388 tm
->tm_wday
= cnt_longest
;
394 /* Match month name. */
396 decided_longest
= s
.decided
;
398 for (cnt
= 0; cnt
< 12; ++cnt
)
405 if (match_string (_NL_CURRENT (LC_TIME
, MON_1
+ cnt
), trp
)
411 && strcmp (_NL_CURRENT (LC_TIME
, MON_1
+ cnt
),
413 decided_longest
= loc
;
416 if (match_string (_NL_CURRENT (LC_TIME
, ABMON_1
+ cnt
), trp
)
422 && strcmp (_NL_CURRENT (LC_TIME
, ABMON_1
+ cnt
),
424 decided_longest
= loc
;
429 && (((trp
= rp
, match_string (month_name
[cnt
], trp
))
431 || ((trp
= rp
, match_string (ab_month_name
[cnt
], trp
))
432 && trp
> rp_longest
)))
436 decided_longest
= raw
;
439 if (rp_longest
== NULL
)
440 /* Does not match a month name. */
443 s
.decided
= decided_longest
;
444 tm
->tm_mon
= cnt_longest
;
449 /* Match locale's date and time format. */
451 if (s
.decided
!= raw
)
453 if (!recursive (_NL_CURRENT (LC_TIME
, D_T_FMT
)))
455 if (s
.decided
== loc
)
462 if (s
.decided
== not &&
463 strcmp (_NL_CURRENT (LC_TIME
, D_T_FMT
), HERE_D_T_FMT
))
471 if (!recursive (HERE_D_T_FMT
))
476 /* Match century number. */
478 get_number (0, 99, 2);
484 /* Match day of month. */
485 get_number (1, 31, 2);
491 if (!recursive ("%Y-%m-%d"))
497 if (s
.decided
!= raw
)
499 if (!recursive (_NL_CURRENT (LC_TIME
, D_FMT
)))
501 if (s
.decided
== loc
)
509 && strcmp (_NL_CURRENT (LC_TIME
, D_FMT
), HERE_D_FMT
))
519 /* Match standard day format. */
520 if (!recursive (HERE_D_FMT
))
526 /* Match hour in 24-hour clock. */
527 get_number (0, 23, 2);
532 /* Match hour in 12-hour clock. GNU extension. */
534 /* Match hour in 12-hour clock. */
535 get_number (1, 12, 2);
536 tm
->tm_hour
= val
% 12;
540 /* Match day number of year. */
541 get_number (1, 366, 3);
542 tm
->tm_yday
= val
- 1;
546 /* Match number of month. */
547 get_number (1, 12, 2);
548 tm
->tm_mon
= val
- 1;
554 get_number (0, 59, 2);
559 /* Match any white space. */
560 while (ISSPACE (*rp
))
564 /* Match locale's equivalent of AM/PM. */
566 if (s
.decided
!= raw
)
568 if (match_string (_NL_CURRENT (LC_TIME
, AM_STR
), rp
))
570 if (strcmp (_NL_CURRENT (LC_TIME
, AM_STR
), HERE_AM_STR
))
575 if (match_string (_NL_CURRENT (LC_TIME
, PM_STR
), rp
))
577 if (strcmp (_NL_CURRENT (LC_TIME
, PM_STR
), HERE_PM_STR
))
585 if (!match_string (HERE_AM_STR
, rp
))
587 if (match_string (HERE_PM_STR
, rp
))
597 if (s
.decided
!= raw
)
599 if (!recursive (_NL_CURRENT (LC_TIME
, T_FMT_AMPM
)))
601 if (s
.decided
== loc
)
608 if (s
.decided
== not &&
609 strcmp (_NL_CURRENT (LC_TIME
, T_FMT_AMPM
),
617 if (!recursive (HERE_T_FMT_AMPM
))
621 if (!recursive ("%H:%M"))
626 /* The number of seconds may be very high so we cannot use
627 the `get_number' macro. Instead read the number
628 character for character and construct the result while
631 if (*rp
< '0' || *rp
> '9')
632 /* We need at least one digit. */
640 while (*rp
>= '0' && *rp
<= '9');
642 if (localtime_r (&secs
, tm
) == NULL
)
643 /* Error in function. */
648 get_number (0, 61, 2);
653 if (s
.decided
!= raw
)
655 if (!recursive (_NL_CURRENT (LC_TIME
, T_FMT
)))
657 if (s
.decided
== loc
)
664 if (strcmp (_NL_CURRENT (LC_TIME
, T_FMT
), HERE_T_FMT
))
673 if (!recursive (HERE_T_FMT
))
677 get_number (1, 7, 1);
678 tm
->tm_wday
= val
% 7;
682 get_number (0, 99, 2);
683 /* XXX This cannot determine any field in TM. */
686 if (*rp
< '0' || *rp
> '9')
688 /* XXX Ignore the number since we would need some more
689 information to compute a real date. */
692 while (*rp
>= '0' && *rp
<= '9');
695 get_number (0, 53, 2);
700 get_number (0, 53, 2);
705 get_number (0, 53, 2);
706 /* XXX This cannot determine any field in TM without some
710 /* Match number of weekday. */
711 get_number (0, 6, 1);
716 match_year_in_century
:
717 /* Match year within century. */
718 get_number (0, 99, 2);
719 /* The "Year 2000: The Millennium Rollover" paper suggests that
720 values in the range 69-99 refer to the twentieth century. */
721 tm
->tm_year
= val
>= 69 ? val
: val
+ 100;
722 /* Indicate that we want to use the century, if specified. */
727 /* Match year including century number. */
728 get_number (0, 9999, 4);
729 tm
->tm_year
= val
- 1900;
734 /* Read timezone but perform no conversion. */
735 while (ISSPACE (*rp
))
737 while (!ISSPACE (*rp
) && *rp
!= '\0')
741 /* We recognize four formats:
742 1. Two digits specify hours.
743 2. Four digits specify hours and minutes.
744 3. Two digits, ':', and two digits specify hours and minutes.
745 4. 'Z' is equivalent to +0000. */
748 while (ISSPACE (*rp
))
756 if (*rp
!= '+' && *rp
!= '-')
758 bool neg
= *rp
++ == '-';
760 while (n
< 4 && *rp
>= '0' && *rp
<= '9')
762 val
= val
* 10 + *rp
++ - '0';
764 if (*rp
== ':' && n
== 2 && isdigit (*(rp
+ 1)))
770 /* Only two or four digits recognized. */
772 else if (val
% 100 >= 60)
773 /* Minutes valid range is 0 through 59. */
775 tm
->tm_gmtoff
= (val
/ 100) * 3600 + (val
% 100) * 60;
777 tm
->tm_gmtoff
= -tm
->tm_gmtoff
;
785 /* Match locale's alternate date and time format. */
786 if (s
.decided
!= raw
)
788 const char *fmt
= _NL_CURRENT (LC_TIME
, ERA_D_T_FMT
);
791 fmt
= _NL_CURRENT (LC_TIME
, D_T_FMT
);
793 if (!recursive (fmt
))
795 if (s
.decided
== loc
)
802 if (strcmp (fmt
, HERE_D_T_FMT
))
809 /* The C locale has no era information, so use the
810 normal representation. */
811 if (!recursive (HERE_D_T_FMT
))
816 if (s
.decided
!= raw
)
820 era
= _nl_select_era_entry (s
.era_cnt HELPER_LOCALE_ARG
);
821 if (era
!= NULL
&& match_string (era
->era_name
, rp
))
830 num_eras
= _NL_CURRENT_WORD (LC_TIME
,
831 _NL_TIME_ERA_NUM_ENTRIES
);
832 for (s
.era_cnt
= 0; s
.era_cnt
< (int) num_eras
;
833 ++s
.era_cnt
, rp
= rp_backup
)
835 era
= _nl_select_era_entry (s
.era_cnt
837 if (era
!= NULL
&& match_string (era
->era_name
, rp
))
843 if (s
.era_cnt
!= (int) num_eras
)
847 if (s
.decided
== loc
)
852 /* The C locale has no era information, so use the
853 normal representation. */
856 if (s
.decided
!= raw
)
858 get_number(0, 9999, 4);
866 assert (s
.decided
== loc
);
868 era
= _nl_select_era_entry (s
.era_cnt HELPER_LOCALE_ARG
);
872 int delta
= ((tm
->tm_year
- era
->offset
)
873 * era
->absolute_direction
);
875 && delta
< (((int64_t) era
->stop_date
[0]
876 - (int64_t) era
->start_date
[0])
877 * era
->absolute_direction
));
885 num_eras
= _NL_CURRENT_WORD (LC_TIME
,
886 _NL_TIME_ERA_NUM_ENTRIES
);
887 for (s
.era_cnt
= 0; s
.era_cnt
< (int) num_eras
; ++s
.era_cnt
)
889 era
= _nl_select_era_entry (s
.era_cnt
893 int delta
= ((tm
->tm_year
- era
->offset
)
894 * era
->absolute_direction
);
896 && delta
< (((int64_t) era
->stop_date
[0]
897 - (int64_t) era
->start_date
[0])
898 * era
->absolute_direction
))
905 if (s
.era_cnt
!= (int) num_eras
)
909 if (s
.decided
== loc
)
915 goto match_year_in_century
;
917 if (s
.decided
!= raw
)
919 num_eras
= _NL_CURRENT_WORD (LC_TIME
,
920 _NL_TIME_ERA_NUM_ENTRIES
);
921 for (s
.era_cnt
= 0; s
.era_cnt
< (int) num_eras
;
922 ++s
.era_cnt
, rp
= rp_backup
)
924 era
= _nl_select_era_entry (s
.era_cnt HELPER_LOCALE_ARG
);
925 if (era
!= NULL
&& recursive (era
->era_format
))
928 if (s
.era_cnt
== (int) num_eras
)
931 if (s
.decided
== loc
)
944 get_number (0, 9999, 4);
945 tm
->tm_year
= val
- 1900;
950 if (s
.decided
!= raw
)
952 const char *fmt
= _NL_CURRENT (LC_TIME
, ERA_D_FMT
);
955 fmt
= _NL_CURRENT (LC_TIME
, D_FMT
);
957 if (!recursive (fmt
))
959 if (s
.decided
== loc
)
966 if (strcmp (fmt
, HERE_D_FMT
))
972 if (!recursive (HERE_D_FMT
))
976 if (s
.decided
!= raw
)
978 const char *fmt
= _NL_CURRENT (LC_TIME
, ERA_T_FMT
);
981 fmt
= _NL_CURRENT (LC_TIME
, T_FMT
);
983 if (!recursive (fmt
))
985 if (s
.decided
== loc
)
992 if (strcmp (fmt
, HERE_T_FMT
))
998 if (!recursive (HERE_T_FMT
))
1006 /* We have no information about the era format. Just use
1007 the normal format. */
1008 if (*fmt
!= 'c' && *fmt
!= 'C' && *fmt
!= 'y' && *fmt
!= 'Y'
1009 && *fmt
!= 'x' && *fmt
!= 'X')
1010 /* This is an illegal format. */
1020 /* Match day of month using alternate numeric symbols. */
1021 get_alt_number (1, 31, 2);
1027 /* Match hour in 24-hour clock using alternate numeric
1029 get_alt_number (0, 23, 2);
1034 /* Match hour in 12-hour clock using alternate numeric
1036 get_alt_number (1, 12, 2);
1037 tm
->tm_hour
= val
% 12;
1041 /* Match month using alternate numeric symbols. */
1042 get_alt_number (1, 12, 2);
1043 tm
->tm_mon
= val
- 1;
1048 /* Match minutes using alternate numeric symbols. */
1049 get_alt_number (0, 59, 2);
1053 /* Match seconds using alternate numeric symbols. */
1054 get_alt_number (0, 61, 2);
1058 get_alt_number (0, 53, 2);
1063 get_alt_number (0, 53, 2);
1068 get_alt_number (0, 53, 2);
1069 /* XXX This cannot determine any field in TM without
1070 further information. */
1073 /* Match number of weekday using alternate numeric symbols. */
1074 get_alt_number (0, 6, 1);
1079 /* Match year within century using alternate numeric symbols. */
1080 get_alt_number (0, 99, 2);
1081 tm
->tm_year
= val
>= 69 ? val
: val
+ 100;
1095 /* Recursive invocation, returning success, so
1096 update parent's struct tm and state. */
1097 *(struct __strptime_state
*) statep
= s
;
1102 if (s
.have_I
&& s
.is_pm
)
1105 if (s
.century
!= -1)
1108 tm
->tm_year
= tm
->tm_year
% 100 + (s
.century
- 19) * 100;
1110 /* Only the century, but not the year. Strange, but so be it. */
1111 tm
->tm_year
= (s
.century
- 19) * 100;
1114 if (s
.era_cnt
!= -1)
1116 era
= _nl_select_era_entry (s
.era_cnt HELPER_LOCALE_ARG
);
1120 tm
->tm_year
= (era
->start_date
[0]
1121 + ((tm
->tm_year
- era
->offset
)
1122 * era
->absolute_direction
));
1124 /* Era start year assumed. */
1125 tm
->tm_year
= era
->start_date
[0];
1130 /* No era found but we have seen an E modifier. Rectify some
1132 if (s
.want_century
&& s
.century
== -1 && tm
->tm_year
< 69)
1136 if (s
.want_xday
&& !s
.have_wday
)
1138 if ( !(s
.have_mon
&& s
.have_mday
) && s
.have_yday
)
1140 /* We don't have tm_mon and/or tm_mday, compute them. */
1142 while (__mon_yday
[__isleap(1900 + tm
->tm_year
)][t_mon
] <= tm
->tm_yday
)
1145 tm
->tm_mon
= t_mon
- 1;
1149 - __mon_yday
[__isleap(1900 + tm
->tm_year
)][t_mon
- 1] + 1);
1153 /* Don't crash in day_of_the_week if tm_mon is uninitialized. */
1154 if (s
.have_mon
|| (unsigned) tm
->tm_mon
<= 11)
1155 day_of_the_week (tm
);
1158 if (s
.want_xday
&& !s
.have_yday
&& (s
.have_mon
|| (unsigned) tm
->tm_mon
<= 11))
1159 day_of_the_year (tm
);
1161 if ((s
.have_uweek
|| s
.have_wweek
) && s
.have_wday
)
1163 int save_wday
= tm
->tm_wday
;
1164 int save_mday
= tm
->tm_mday
;
1165 int save_mon
= tm
->tm_mon
;
1166 int w_offset
= s
.have_uweek
? 0 : 1;
1170 day_of_the_week (tm
);
1172 tm
->tm_mday
= save_mday
;
1174 tm
->tm_mon
= save_mon
;
1177 tm
->tm_yday
= ((7 - (tm
->tm_wday
- w_offset
)) % 7
1178 + (s
.week_no
- 1) * 7
1179 + (save_wday
- w_offset
+ 7) % 7);
1181 if (!s
.have_mday
|| !s
.have_mon
)
1184 while (__mon_yday
[__isleap(1900 + tm
->tm_year
)][t_mon
]
1188 tm
->tm_mon
= t_mon
- 1;
1192 - __mon_yday
[__isleap(1900 + tm
->tm_year
)][t_mon
- 1] + 1);
1195 tm
->tm_wday
= save_wday
;
1203 strptime (const char *buf
, const char *format
, struct tm
*tm LOCALE_PARAM
)
1205 return __strptime_internal (buf
, format
, tm
, NULL LOCALE_ARG
);
1209 weak_alias (__strptime_l
, strptime_l
)