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));
238 __strptime_internal (const char *rp
, const char *fmt
, struct tm
*tmp
,
239 void *statep LOCALE_PARAM
)
242 struct __locale_data
*const current
= locale
->__locales
[LC_TIME
];
245 const char *rp_backup
;
246 const char *rp_longest
;
251 struct era_entry
*era
= NULL
;
252 enum ptime_locale_status
{ not, loc
, raw
} decided_longest
;
253 struct __strptime_state
255 unsigned int have_I
: 1;
256 unsigned int have_wday
: 1;
257 unsigned int have_yday
: 1;
258 unsigned int have_mon
: 1;
259 unsigned int have_mday
: 1;
260 unsigned int have_uweek
: 1;
261 unsigned int have_wweek
: 1;
262 unsigned int is_pm
: 1;
263 unsigned int want_century
: 1;
264 unsigned int want_era
: 1;
265 unsigned int want_xday
: 1;
266 enum ptime_locale_status decided
: 2;
276 memset (&s
, 0, sizeof (s
));
288 s
= *(struct __strptime_state
*) statep
;
295 /* A white space in the format string matches 0 more or white
296 space in the input string. */
299 while (ISSPACE (*rp
))
305 /* Any character but `%' must be matched by the same character
306 in the iput string. */
309 match_char (*fmt
++, *rp
++);
314 /* We discard strftime modifiers. */
315 while (*fmt
== '-' || *fmt
== '_' || *fmt
== '0'
316 || *fmt
== '^' || *fmt
== '#')
319 /* And field width. */
320 while (*fmt
>= '0' && *fmt
<= '9')
324 /* We need this for handling the `E' modifier. */
328 /* Make back up of current processing pointer. */
334 /* Match the `%' character itself. */
335 match_char ('%', *rp
++);
339 /* Match day of week. */
341 decided_longest
= s
.decided
;
343 for (cnt
= 0; cnt
< 7; ++cnt
)
350 if (match_string (_NL_CURRENT (LC_TIME
, DAY_1
+ cnt
), trp
)
356 && strcmp (_NL_CURRENT (LC_TIME
, DAY_1
+ cnt
),
358 decided_longest
= loc
;
361 if (match_string (_NL_CURRENT (LC_TIME
, ABDAY_1
+ cnt
), trp
)
367 && strcmp (_NL_CURRENT (LC_TIME
, ABDAY_1
+ cnt
),
368 ab_weekday_name
[cnt
]))
369 decided_longest
= loc
;
374 && (((trp
= rp
, match_string (weekday_name
[cnt
], trp
))
376 || ((trp
= rp
, match_string (ab_weekday_name
[cnt
], rp
))
377 && trp
> rp_longest
)))
381 decided_longest
= raw
;
384 if (rp_longest
== NULL
)
385 /* Does not match a weekday name. */
388 s
.decided
= decided_longest
;
389 tm
->tm_wday
= cnt_longest
;
395 /* Match month name. */
397 decided_longest
= s
.decided
;
399 for (cnt
= 0; cnt
< 12; ++cnt
)
406 if (match_string (_NL_CURRENT (LC_TIME
, MON_1
+ cnt
), trp
)
412 && strcmp (_NL_CURRENT (LC_TIME
, MON_1
+ cnt
),
414 decided_longest
= loc
;
417 if (match_string (_NL_CURRENT (LC_TIME
, ABMON_1
+ cnt
), trp
)
423 && strcmp (_NL_CURRENT (LC_TIME
, ABMON_1
+ cnt
),
425 decided_longest
= loc
;
430 && (((trp
= rp
, match_string (month_name
[cnt
], trp
))
432 || ((trp
= rp
, match_string (ab_month_name
[cnt
], trp
))
433 && trp
> rp_longest
)))
437 decided_longest
= raw
;
440 if (rp_longest
== NULL
)
441 /* Does not match a month name. */
444 s
.decided
= decided_longest
;
445 tm
->tm_mon
= cnt_longest
;
450 /* Match locale's date and time format. */
452 if (s
.decided
!= raw
)
454 if (!recursive (_NL_CURRENT (LC_TIME
, D_T_FMT
)))
456 if (s
.decided
== loc
)
463 if (s
.decided
== not &&
464 strcmp (_NL_CURRENT (LC_TIME
, D_T_FMT
), HERE_D_T_FMT
))
472 if (!recursive (HERE_D_T_FMT
))
477 /* Match century number. */
479 get_number (0, 99, 2);
485 /* Match day of month. */
486 get_number (1, 31, 2);
492 if (!recursive ("%Y-%m-%d"))
498 if (s
.decided
!= raw
)
500 if (!recursive (_NL_CURRENT (LC_TIME
, D_FMT
)))
502 if (s
.decided
== loc
)
510 && strcmp (_NL_CURRENT (LC_TIME
, D_FMT
), HERE_D_FMT
))
520 /* Match standard day format. */
521 if (!recursive (HERE_D_FMT
))
527 /* Match hour in 24-hour clock. */
528 get_number (0, 23, 2);
533 /* Match hour in 12-hour clock. GNU extension. */
535 /* Match hour in 12-hour clock. */
536 get_number (1, 12, 2);
537 tm
->tm_hour
= val
% 12;
541 /* Match day number of year. */
542 get_number (1, 366, 3);
543 tm
->tm_yday
= val
- 1;
547 /* Match number of month. */
548 get_number (1, 12, 2);
549 tm
->tm_mon
= val
- 1;
555 get_number (0, 59, 2);
560 /* Match any white space. */
561 while (ISSPACE (*rp
))
565 /* Match locale's equivalent of AM/PM. */
567 if (s
.decided
!= raw
)
569 if (match_string (_NL_CURRENT (LC_TIME
, AM_STR
), rp
))
571 if (strcmp (_NL_CURRENT (LC_TIME
, AM_STR
), HERE_AM_STR
))
576 if (match_string (_NL_CURRENT (LC_TIME
, PM_STR
), rp
))
578 if (strcmp (_NL_CURRENT (LC_TIME
, PM_STR
), HERE_PM_STR
))
586 if (!match_string (HERE_AM_STR
, rp
))
588 if (match_string (HERE_PM_STR
, rp
))
598 if (s
.decided
!= raw
)
600 if (!recursive (_NL_CURRENT (LC_TIME
, T_FMT_AMPM
)))
602 if (s
.decided
== loc
)
609 if (s
.decided
== not &&
610 strcmp (_NL_CURRENT (LC_TIME
, T_FMT_AMPM
),
618 if (!recursive (HERE_T_FMT_AMPM
))
622 if (!recursive ("%H:%M"))
627 /* The number of seconds may be very high so we cannot use
628 the `get_number' macro. Instead read the number
629 character for character and construct the result while
632 if (*rp
< '0' || *rp
> '9')
633 /* We need at least one digit. */
641 while (*rp
>= '0' && *rp
<= '9');
643 if (localtime_r (&secs
, tm
) == NULL
)
644 /* Error in function. */
649 get_number (0, 61, 2);
654 if (s
.decided
!= raw
)
656 if (!recursive (_NL_CURRENT (LC_TIME
, T_FMT
)))
658 if (s
.decided
== loc
)
665 if (strcmp (_NL_CURRENT (LC_TIME
, T_FMT
), HERE_T_FMT
))
674 if (!recursive (HERE_T_FMT
))
678 get_number (1, 7, 1);
679 tm
->tm_wday
= val
% 7;
683 get_number (0, 99, 2);
684 /* XXX This cannot determine any field in TM. */
687 if (*rp
< '0' || *rp
> '9')
689 /* XXX Ignore the number since we would need some more
690 information to compute a real date. */
693 while (*rp
>= '0' && *rp
<= '9');
696 get_number (0, 53, 2);
701 get_number (0, 53, 2);
706 get_number (0, 53, 2);
707 /* XXX This cannot determine any field in TM without some
711 /* Match number of weekday. */
712 get_number (0, 6, 1);
717 match_year_in_century
:
718 /* Match year within century. */
719 get_number (0, 99, 2);
720 /* The "Year 2000: The Millennium Rollover" paper suggests that
721 values in the range 69-99 refer to the twentieth century. */
722 tm
->tm_year
= val
>= 69 ? val
: val
+ 100;
723 /* Indicate that we want to use the century, if specified. */
728 /* Match year including century number. */
729 get_number (0, 9999, 4);
730 tm
->tm_year
= val
- 1900;
735 /* Read timezone but perform no conversion. */
736 while (ISSPACE (*rp
))
738 while (!ISSPACE (*rp
) && *rp
!= '\0')
742 /* We recognize four formats:
743 1. Two digits specify hours.
744 2. Four digits specify hours and minutes.
745 3. Two digits, ':', and two digits specify hours and minutes.
746 4. 'Z' is equivalent to +0000. */
749 while (ISSPACE (*rp
))
757 if (*rp
!= '+' && *rp
!= '-')
759 bool neg
= *rp
++ == '-';
761 while (n
< 4 && *rp
>= '0' && *rp
<= '9')
763 val
= val
* 10 + *rp
++ - '0';
765 if (*rp
== ':' && n
== 2 && isdigit (*(rp
+ 1)))
771 /* Only two or four digits recognized. */
773 else if (val
% 100 >= 60)
774 /* Minutes valid range is 0 through 59. */
776 tm
->tm_gmtoff
= (val
/ 100) * 3600 + (val
% 100) * 60;
778 tm
->tm_gmtoff
= -tm
->tm_gmtoff
;
786 /* Match locale's alternate date and time format. */
787 if (s
.decided
!= raw
)
789 const char *fmt
= _NL_CURRENT (LC_TIME
, ERA_D_T_FMT
);
792 fmt
= _NL_CURRENT (LC_TIME
, D_T_FMT
);
794 if (!recursive (fmt
))
796 if (s
.decided
== loc
)
803 if (strcmp (fmt
, HERE_D_T_FMT
))
810 /* The C locale has no era information, so use the
811 normal representation. */
812 if (!recursive (HERE_D_T_FMT
))
817 if (s
.decided
!= raw
)
821 era
= _nl_select_era_entry (s
.era_cnt HELPER_LOCALE_ARG
);
822 if (era
!= NULL
&& match_string (era
->era_name
, rp
))
831 num_eras
= _NL_CURRENT_WORD (LC_TIME
,
832 _NL_TIME_ERA_NUM_ENTRIES
);
833 for (s
.era_cnt
= 0; s
.era_cnt
< (int) num_eras
;
834 ++s
.era_cnt
, rp
= rp_backup
)
836 era
= _nl_select_era_entry (s
.era_cnt
838 if (era
!= NULL
&& match_string (era
->era_name
, rp
))
844 if (s
.era_cnt
!= (int) num_eras
)
848 if (s
.decided
== loc
)
853 /* The C locale has no era information, so use the
854 normal representation. */
857 if (s
.decided
!= raw
)
859 get_number(0, 9999, 4);
867 assert (s
.decided
== loc
);
869 era
= _nl_select_era_entry (s
.era_cnt HELPER_LOCALE_ARG
);
873 int delta
= ((tm
->tm_year
- era
->offset
)
874 * era
->absolute_direction
);
876 && delta
< (((int64_t) era
->stop_date
[0]
877 - (int64_t) era
->start_date
[0])
878 * era
->absolute_direction
));
886 num_eras
= _NL_CURRENT_WORD (LC_TIME
,
887 _NL_TIME_ERA_NUM_ENTRIES
);
888 for (s
.era_cnt
= 0; s
.era_cnt
< (int) num_eras
; ++s
.era_cnt
)
890 era
= _nl_select_era_entry (s
.era_cnt
894 int delta
= ((tm
->tm_year
- era
->offset
)
895 * era
->absolute_direction
);
897 && delta
< (((int64_t) era
->stop_date
[0]
898 - (int64_t) era
->start_date
[0])
899 * era
->absolute_direction
))
906 if (s
.era_cnt
!= (int) num_eras
)
910 if (s
.decided
== loc
)
916 goto match_year_in_century
;
918 if (s
.decided
!= raw
)
920 num_eras
= _NL_CURRENT_WORD (LC_TIME
,
921 _NL_TIME_ERA_NUM_ENTRIES
);
922 for (s
.era_cnt
= 0; s
.era_cnt
< (int) num_eras
;
923 ++s
.era_cnt
, rp
= rp_backup
)
925 era
= _nl_select_era_entry (s
.era_cnt HELPER_LOCALE_ARG
);
926 if (era
!= NULL
&& recursive (era
->era_format
))
929 if (s
.era_cnt
== (int) num_eras
)
932 if (s
.decided
== loc
)
945 get_number (0, 9999, 4);
946 tm
->tm_year
= val
- 1900;
951 if (s
.decided
!= raw
)
953 const char *fmt
= _NL_CURRENT (LC_TIME
, ERA_D_FMT
);
956 fmt
= _NL_CURRENT (LC_TIME
, D_FMT
);
958 if (!recursive (fmt
))
960 if (s
.decided
== loc
)
967 if (strcmp (fmt
, HERE_D_FMT
))
973 if (!recursive (HERE_D_FMT
))
977 if (s
.decided
!= raw
)
979 const char *fmt
= _NL_CURRENT (LC_TIME
, ERA_T_FMT
);
982 fmt
= _NL_CURRENT (LC_TIME
, T_FMT
);
984 if (!recursive (fmt
))
986 if (s
.decided
== loc
)
993 if (strcmp (fmt
, HERE_T_FMT
))
999 if (!recursive (HERE_T_FMT
))
1007 /* We have no information about the era format. Just use
1008 the normal format. */
1009 if (*fmt
!= 'c' && *fmt
!= 'C' && *fmt
!= 'y' && *fmt
!= 'Y'
1010 && *fmt
!= 'x' && *fmt
!= 'X')
1011 /* This is an illegal format. */
1021 /* Match day of month using alternate numeric symbols. */
1022 get_alt_number (1, 31, 2);
1028 /* Match hour in 24-hour clock using alternate numeric
1030 get_alt_number (0, 23, 2);
1035 /* Match hour in 12-hour clock using alternate numeric
1037 get_alt_number (1, 12, 2);
1038 tm
->tm_hour
= val
% 12;
1042 /* Match month using alternate numeric symbols. */
1043 get_alt_number (1, 12, 2);
1044 tm
->tm_mon
= val
- 1;
1049 /* Match minutes using alternate numeric symbols. */
1050 get_alt_number (0, 59, 2);
1054 /* Match seconds using alternate numeric symbols. */
1055 get_alt_number (0, 61, 2);
1059 get_alt_number (0, 53, 2);
1064 get_alt_number (0, 53, 2);
1069 get_alt_number (0, 53, 2);
1070 /* XXX This cannot determine any field in TM without
1071 further information. */
1074 /* Match number of weekday using alternate numeric symbols. */
1075 get_alt_number (0, 6, 1);
1080 /* Match year within century using alternate numeric symbols. */
1081 get_alt_number (0, 99, 2);
1082 tm
->tm_year
= val
>= 69 ? val
: val
+ 100;
1096 /* Recursive invocation, returning success, so
1097 update parent's struct tm and state. */
1098 *(struct __strptime_state
*) statep
= s
;
1103 if (s
.have_I
&& s
.is_pm
)
1106 if (s
.century
!= -1)
1109 tm
->tm_year
= tm
->tm_year
% 100 + (s
.century
- 19) * 100;
1111 /* Only the century, but not the year. Strange, but so be it. */
1112 tm
->tm_year
= (s
.century
- 19) * 100;
1115 if (s
.era_cnt
!= -1)
1117 era
= _nl_select_era_entry (s
.era_cnt HELPER_LOCALE_ARG
);
1121 tm
->tm_year
= (era
->start_date
[0]
1122 + ((tm
->tm_year
- era
->offset
)
1123 * era
->absolute_direction
));
1125 /* Era start year assumed. */
1126 tm
->tm_year
= era
->start_date
[0];
1131 /* No era found but we have seen an E modifier. Rectify some
1133 if (s
.want_century
&& s
.century
== -1 && tm
->tm_year
< 69)
1137 if (s
.want_xday
&& !s
.have_wday
)
1139 if ( !(s
.have_mon
&& s
.have_mday
) && s
.have_yday
)
1141 /* We don't have tm_mon and/or tm_mday, compute them. */
1143 while (__mon_yday
[__isleap(1900 + tm
->tm_year
)][t_mon
] <= tm
->tm_yday
)
1146 tm
->tm_mon
= t_mon
- 1;
1150 - __mon_yday
[__isleap(1900 + tm
->tm_year
)][t_mon
- 1] + 1);
1154 /* Don't crash in day_of_the_week if tm_mon is uninitialized. */
1155 if (s
.have_mon
|| (unsigned) tm
->tm_mon
<= 11)
1156 day_of_the_week (tm
);
1159 if (s
.want_xday
&& !s
.have_yday
&& (s
.have_mon
|| (unsigned) tm
->tm_mon
<= 11))
1160 day_of_the_year (tm
);
1162 if ((s
.have_uweek
|| s
.have_wweek
) && s
.have_wday
)
1164 int save_wday
= tm
->tm_wday
;
1165 int save_mday
= tm
->tm_mday
;
1166 int save_mon
= tm
->tm_mon
;
1167 int w_offset
= s
.have_uweek
? 0 : 1;
1171 day_of_the_week (tm
);
1173 tm
->tm_mday
= save_mday
;
1175 tm
->tm_mon
= save_mon
;
1178 tm
->tm_yday
= ((7 - (tm
->tm_wday
- w_offset
)) % 7
1179 + (s
.week_no
- 1) * 7
1180 + (save_wday
- w_offset
+ 7) % 7);
1182 if (!s
.have_mday
|| !s
.have_mon
)
1185 while (__mon_yday
[__isleap(1900 + tm
->tm_year
)][t_mon
]
1189 tm
->tm_mon
= t_mon
- 1;
1193 - __mon_yday
[__isleap(1900 + tm
->tm_year
)][t_mon
- 1] + 1);
1196 tm
->tm_wday
= save_wday
;
1204 strptime (const char *buf
, const char *format
, struct tm
*tm LOCALE_PARAM
)
1206 return __strptime_internal (buf
, format
, tm
, NULL LOCALE_ARG
);
1210 weak_alias (__strptime_l
, strptime_l
)