1 /* Copyright (C) 2002-2015 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
185 # define LOCALE_ARG , locale
186 # define LOCALE_PARAM_PROTO , __locale_t locale
187 # define LOCALE_PARAM_DECL __locale_t locale;
188 # define HELPER_LOCALE_ARG , current
189 # define ISSPACE(Ch) __isspace_l (Ch, locale)
191 # define LOCALE_PARAM
193 # define LOCALE_PARAM_DECL
194 # define LOCALE_PARAM_PROTO
195 # define HELPER_LOCALE_ARG
196 # define ISSPACE(Ch) isspace (Ch)
203 /* Nonzero if YEAR is a leap year (every 4 years,
204 except every 100th isn't, and every 400th is). */
205 # define __isleap(year) \
206 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
209 /* Compute the day of the week. */
211 day_of_the_week (struct tm
*tm
)
213 /* We know that January 1st 1970 was a Thursday (= 4). Compute the
214 difference between this data in the one on TM and so determine
216 int corr_year
= 1900 + tm
->tm_year
- (tm
->tm_mon
< 2);
218 + (365 * (tm
->tm_year
- 70))
220 - ((corr_year
/ 4) / 25) + ((corr_year
/ 4) % 25 < 0)
221 + (((corr_year
/ 4) / 25) / 4)
222 + __mon_yday
[0][tm
->tm_mon
]
224 tm
->tm_wday
= ((wday
% 7) + 7) % 7;
227 /* Compute the day of the year. */
229 day_of_the_year (struct tm
*tm
)
231 tm
->tm_yday
= (__mon_yday
[__isleap (1900 + tm
->tm_year
)][tm
->tm_mon
]
232 + (tm
->tm_mday
- 1));
242 __strptime_internal (rp
, fmt
, tmp
, statep LOCALE_PARAM
)
250 struct __locale_data
*const current
= locale
->__locales
[LC_TIME
];
253 const char *rp_backup
;
254 const char *rp_longest
;
259 struct era_entry
*era
= NULL
;
260 enum ptime_locale_status
{ not, loc
, raw
} decided_longest
;
261 struct __strptime_state
263 unsigned int have_I
: 1;
264 unsigned int have_wday
: 1;
265 unsigned int have_yday
: 1;
266 unsigned int have_mon
: 1;
267 unsigned int have_mday
: 1;
268 unsigned int have_uweek
: 1;
269 unsigned int have_wweek
: 1;
270 unsigned int is_pm
: 1;
271 unsigned int want_century
: 1;
272 unsigned int want_era
: 1;
273 unsigned int want_xday
: 1;
274 enum ptime_locale_status decided
: 2;
284 memset (&s
, 0, sizeof (s
));
296 s
= *(struct __strptime_state
*) statep
;
303 /* A white space in the format string matches 0 more or white
304 space in the input string. */
307 while (ISSPACE (*rp
))
313 /* Any character but `%' must be matched by the same character
314 in the iput string. */
317 match_char (*fmt
++, *rp
++);
322 /* We discard strftime modifiers. */
323 while (*fmt
== '-' || *fmt
== '_' || *fmt
== '0'
324 || *fmt
== '^' || *fmt
== '#')
327 /* And field width. */
328 while (*fmt
>= '0' && *fmt
<= '9')
332 /* We need this for handling the `E' modifier. */
336 /* Make back up of current processing pointer. */
342 /* Match the `%' character itself. */
343 match_char ('%', *rp
++);
347 /* Match day of week. */
349 decided_longest
= s
.decided
;
351 for (cnt
= 0; cnt
< 7; ++cnt
)
358 if (match_string (_NL_CURRENT (LC_TIME
, DAY_1
+ cnt
), trp
)
364 && strcmp (_NL_CURRENT (LC_TIME
, DAY_1
+ cnt
),
366 decided_longest
= loc
;
369 if (match_string (_NL_CURRENT (LC_TIME
, ABDAY_1
+ cnt
), trp
)
375 && strcmp (_NL_CURRENT (LC_TIME
, ABDAY_1
+ cnt
),
376 ab_weekday_name
[cnt
]))
377 decided_longest
= loc
;
382 && (((trp
= rp
, match_string (weekday_name
[cnt
], trp
))
384 || ((trp
= rp
, match_string (ab_weekday_name
[cnt
], rp
))
385 && trp
> rp_longest
)))
389 decided_longest
= raw
;
392 if (rp_longest
== NULL
)
393 /* Does not match a weekday name. */
396 s
.decided
= decided_longest
;
397 tm
->tm_wday
= cnt_longest
;
403 /* Match month name. */
405 decided_longest
= s
.decided
;
407 for (cnt
= 0; cnt
< 12; ++cnt
)
414 if (match_string (_NL_CURRENT (LC_TIME
, MON_1
+ cnt
), trp
)
420 && strcmp (_NL_CURRENT (LC_TIME
, MON_1
+ cnt
),
422 decided_longest
= loc
;
425 if (match_string (_NL_CURRENT (LC_TIME
, ABMON_1
+ cnt
), trp
)
431 && strcmp (_NL_CURRENT (LC_TIME
, ABMON_1
+ cnt
),
433 decided_longest
= loc
;
438 && (((trp
= rp
, match_string (month_name
[cnt
], trp
))
440 || ((trp
= rp
, match_string (ab_month_name
[cnt
], trp
))
441 && trp
> rp_longest
)))
445 decided_longest
= raw
;
448 if (rp_longest
== NULL
)
449 /* Does not match a month name. */
452 s
.decided
= decided_longest
;
453 tm
->tm_mon
= cnt_longest
;
458 /* Match locale's date and time format. */
460 if (s
.decided
!= raw
)
462 if (!recursive (_NL_CURRENT (LC_TIME
, D_T_FMT
)))
464 if (s
.decided
== loc
)
471 if (s
.decided
== not &&
472 strcmp (_NL_CURRENT (LC_TIME
, D_T_FMT
), HERE_D_T_FMT
))
480 if (!recursive (HERE_D_T_FMT
))
485 /* Match century number. */
487 get_number (0, 99, 2);
493 /* Match day of month. */
494 get_number (1, 31, 2);
500 if (!recursive ("%Y-%m-%d"))
506 if (s
.decided
!= raw
)
508 if (!recursive (_NL_CURRENT (LC_TIME
, D_FMT
)))
510 if (s
.decided
== loc
)
518 && strcmp (_NL_CURRENT (LC_TIME
, D_FMT
), HERE_D_FMT
))
528 /* Match standard day format. */
529 if (!recursive (HERE_D_FMT
))
535 /* Match hour in 24-hour clock. */
536 get_number (0, 23, 2);
541 /* Match hour in 12-hour clock. GNU extension. */
543 /* Match hour in 12-hour clock. */
544 get_number (1, 12, 2);
545 tm
->tm_hour
= val
% 12;
549 /* Match day number of year. */
550 get_number (1, 366, 3);
551 tm
->tm_yday
= val
- 1;
555 /* Match number of month. */
556 get_number (1, 12, 2);
557 tm
->tm_mon
= val
- 1;
563 get_number (0, 59, 2);
568 /* Match any white space. */
569 while (ISSPACE (*rp
))
573 /* Match locale's equivalent of AM/PM. */
575 if (s
.decided
!= raw
)
577 if (match_string (_NL_CURRENT (LC_TIME
, AM_STR
), rp
))
579 if (strcmp (_NL_CURRENT (LC_TIME
, AM_STR
), HERE_AM_STR
))
584 if (match_string (_NL_CURRENT (LC_TIME
, PM_STR
), rp
))
586 if (strcmp (_NL_CURRENT (LC_TIME
, PM_STR
), HERE_PM_STR
))
594 if (!match_string (HERE_AM_STR
, rp
))
596 if (match_string (HERE_PM_STR
, rp
))
606 if (s
.decided
!= raw
)
608 if (!recursive (_NL_CURRENT (LC_TIME
, T_FMT_AMPM
)))
610 if (s
.decided
== loc
)
617 if (s
.decided
== not &&
618 strcmp (_NL_CURRENT (LC_TIME
, T_FMT_AMPM
),
626 if (!recursive (HERE_T_FMT_AMPM
))
630 if (!recursive ("%H:%M"))
635 /* The number of seconds may be very high so we cannot use
636 the `get_number' macro. Instead read the number
637 character for character and construct the result while
640 if (*rp
< '0' || *rp
> '9')
641 /* We need at least one digit. */
649 while (*rp
>= '0' && *rp
<= '9');
651 if (localtime_r (&secs
, tm
) == NULL
)
652 /* Error in function. */
657 get_number (0, 61, 2);
662 if (s
.decided
!= raw
)
664 if (!recursive (_NL_CURRENT (LC_TIME
, T_FMT
)))
666 if (s
.decided
== loc
)
673 if (strcmp (_NL_CURRENT (LC_TIME
, T_FMT
), HERE_T_FMT
))
682 if (!recursive (HERE_T_FMT
))
686 get_number (1, 7, 1);
687 tm
->tm_wday
= val
% 7;
691 get_number (0, 99, 2);
692 /* XXX This cannot determine any field in TM. */
695 if (*rp
< '0' || *rp
> '9')
697 /* XXX Ignore the number since we would need some more
698 information to compute a real date. */
701 while (*rp
>= '0' && *rp
<= '9');
704 get_number (0, 53, 2);
709 get_number (0, 53, 2);
714 get_number (0, 53, 2);
715 /* XXX This cannot determine any field in TM without some
719 /* Match number of weekday. */
720 get_number (0, 6, 1);
725 match_year_in_century
:
726 /* Match year within century. */
727 get_number (0, 99, 2);
728 /* The "Year 2000: The Millennium Rollover" paper suggests that
729 values in the range 69-99 refer to the twentieth century. */
730 tm
->tm_year
= val
>= 69 ? val
: val
+ 100;
731 /* Indicate that we want to use the century, if specified. */
736 /* Match year including century number. */
737 get_number (0, 9999, 4);
738 tm
->tm_year
= val
- 1900;
743 /* Read timezone but perform no conversion. */
744 while (ISSPACE (*rp
))
746 while (!ISSPACE (*rp
) && *rp
!= '\0')
750 /* We recognize four formats:
751 1. Two digits specify hours.
752 2. Four digits specify hours and minutes.
753 3. Two digits, ':', and two digits specify hours and minutes.
754 4. 'Z' is equivalent to +0000. */
757 while (ISSPACE (*rp
))
765 if (*rp
!= '+' && *rp
!= '-')
767 bool neg
= *rp
++ == '-';
769 while (n
< 4 && *rp
>= '0' && *rp
<= '9')
771 val
= val
* 10 + *rp
++ - '0';
773 if (*rp
== ':' && n
== 2 && isdigit (*(rp
+ 1)))
779 /* Only two or four digits recognized. */
781 else if (val
% 100 >= 60)
782 /* Minutes valid range is 0 through 59. */
784 tm
->tm_gmtoff
= (val
/ 100) * 3600 + (val
% 100) * 60;
786 tm
->tm_gmtoff
= -tm
->tm_gmtoff
;
794 /* Match locale's alternate date and time format. */
795 if (s
.decided
!= raw
)
797 const char *fmt
= _NL_CURRENT (LC_TIME
, ERA_D_T_FMT
);
800 fmt
= _NL_CURRENT (LC_TIME
, D_T_FMT
);
802 if (!recursive (fmt
))
804 if (s
.decided
== loc
)
811 if (strcmp (fmt
, HERE_D_T_FMT
))
818 /* The C locale has no era information, so use the
819 normal representation. */
820 if (!recursive (HERE_D_T_FMT
))
825 if (s
.decided
!= raw
)
829 era
= _nl_select_era_entry (s
.era_cnt HELPER_LOCALE_ARG
);
830 if (era
!= NULL
&& match_string (era
->era_name
, rp
))
839 num_eras
= _NL_CURRENT_WORD (LC_TIME
,
840 _NL_TIME_ERA_NUM_ENTRIES
);
841 for (s
.era_cnt
= 0; s
.era_cnt
< (int) num_eras
;
842 ++s
.era_cnt
, rp
= rp_backup
)
844 era
= _nl_select_era_entry (s
.era_cnt
846 if (era
!= NULL
&& match_string (era
->era_name
, rp
))
852 if (s
.era_cnt
!= (int) num_eras
)
856 if (s
.decided
== loc
)
861 /* The C locale has no era information, so use the
862 normal representation. */
865 if (s
.decided
!= raw
)
867 get_number(0, 9999, 4);
875 assert (s
.decided
== loc
);
877 era
= _nl_select_era_entry (s
.era_cnt HELPER_LOCALE_ARG
);
881 int delta
= ((tm
->tm_year
- era
->offset
)
882 * era
->absolute_direction
);
884 && delta
< (((int64_t) era
->stop_date
[0]
885 - (int64_t) era
->start_date
[0])
886 * era
->absolute_direction
));
894 num_eras
= _NL_CURRENT_WORD (LC_TIME
,
895 _NL_TIME_ERA_NUM_ENTRIES
);
896 for (s
.era_cnt
= 0; s
.era_cnt
< (int) num_eras
; ++s
.era_cnt
)
898 era
= _nl_select_era_entry (s
.era_cnt
902 int delta
= ((tm
->tm_year
- era
->offset
)
903 * era
->absolute_direction
);
905 && delta
< (((int64_t) era
->stop_date
[0]
906 - (int64_t) era
->start_date
[0])
907 * era
->absolute_direction
))
914 if (s
.era_cnt
!= (int) num_eras
)
918 if (s
.decided
== loc
)
924 goto match_year_in_century
;
926 if (s
.decided
!= raw
)
928 num_eras
= _NL_CURRENT_WORD (LC_TIME
,
929 _NL_TIME_ERA_NUM_ENTRIES
);
930 for (s
.era_cnt
= 0; s
.era_cnt
< (int) num_eras
;
931 ++s
.era_cnt
, rp
= rp_backup
)
933 era
= _nl_select_era_entry (s
.era_cnt HELPER_LOCALE_ARG
);
934 if (era
!= NULL
&& recursive (era
->era_format
))
937 if (s
.era_cnt
== (int) num_eras
)
940 if (s
.decided
== loc
)
953 get_number (0, 9999, 4);
954 tm
->tm_year
= val
- 1900;
959 if (s
.decided
!= raw
)
961 const char *fmt
= _NL_CURRENT (LC_TIME
, ERA_D_FMT
);
964 fmt
= _NL_CURRENT (LC_TIME
, D_FMT
);
966 if (!recursive (fmt
))
968 if (s
.decided
== loc
)
975 if (strcmp (fmt
, HERE_D_FMT
))
981 if (!recursive (HERE_D_FMT
))
985 if (s
.decided
!= raw
)
987 const char *fmt
= _NL_CURRENT (LC_TIME
, ERA_T_FMT
);
990 fmt
= _NL_CURRENT (LC_TIME
, T_FMT
);
992 if (!recursive (fmt
))
994 if (s
.decided
== loc
)
1001 if (strcmp (fmt
, HERE_T_FMT
))
1007 if (!recursive (HERE_T_FMT
))
1015 /* We have no information about the era format. Just use
1016 the normal format. */
1017 if (*fmt
!= 'c' && *fmt
!= 'C' && *fmt
!= 'y' && *fmt
!= 'Y'
1018 && *fmt
!= 'x' && *fmt
!= 'X')
1019 /* This is an illegal format. */
1029 /* Match day of month using alternate numeric symbols. */
1030 get_alt_number (1, 31, 2);
1036 /* Match hour in 24-hour clock using alternate numeric
1038 get_alt_number (0, 23, 2);
1043 /* Match hour in 12-hour clock using alternate numeric
1045 get_alt_number (1, 12, 2);
1046 tm
->tm_hour
= val
% 12;
1050 /* Match month using alternate numeric symbols. */
1051 get_alt_number (1, 12, 2);
1052 tm
->tm_mon
= val
- 1;
1057 /* Match minutes using alternate numeric symbols. */
1058 get_alt_number (0, 59, 2);
1062 /* Match seconds using alternate numeric symbols. */
1063 get_alt_number (0, 61, 2);
1067 get_alt_number (0, 53, 2);
1072 get_alt_number (0, 53, 2);
1077 get_alt_number (0, 53, 2);
1078 /* XXX This cannot determine any field in TM without
1079 further information. */
1082 /* Match number of weekday using alternate numeric symbols. */
1083 get_alt_number (0, 6, 1);
1088 /* Match year within century using alternate numeric symbols. */
1089 get_alt_number (0, 99, 2);
1090 tm
->tm_year
= val
>= 69 ? val
: val
+ 100;
1104 /* Recursive invocation, returning success, so
1105 update parent's struct tm and state. */
1106 *(struct __strptime_state
*) statep
= s
;
1111 if (s
.have_I
&& s
.is_pm
)
1114 if (s
.century
!= -1)
1117 tm
->tm_year
= tm
->tm_year
% 100 + (s
.century
- 19) * 100;
1119 /* Only the century, but not the year. Strange, but so be it. */
1120 tm
->tm_year
= (s
.century
- 19) * 100;
1123 if (s
.era_cnt
!= -1)
1125 era
= _nl_select_era_entry (s
.era_cnt HELPER_LOCALE_ARG
);
1129 tm
->tm_year
= (era
->start_date
[0]
1130 + ((tm
->tm_year
- era
->offset
)
1131 * era
->absolute_direction
));
1133 /* Era start year assumed. */
1134 tm
->tm_year
= era
->start_date
[0];
1139 /* No era found but we have seen an E modifier. Rectify some
1141 if (s
.want_century
&& s
.century
== -1 && tm
->tm_year
< 69)
1145 if (s
.want_xday
&& !s
.have_wday
)
1147 if ( !(s
.have_mon
&& s
.have_mday
) && s
.have_yday
)
1149 /* We don't have tm_mon and/or tm_mday, compute them. */
1151 while (__mon_yday
[__isleap(1900 + tm
->tm_year
)][t_mon
] <= tm
->tm_yday
)
1154 tm
->tm_mon
= t_mon
- 1;
1158 - __mon_yday
[__isleap(1900 + tm
->tm_year
)][t_mon
- 1] + 1);
1162 /* Don't crash in day_of_the_week if tm_mon is uninitialized. */
1163 if (s
.have_mon
|| (unsigned) tm
->tm_mon
<= 11)
1164 day_of_the_week (tm
);
1167 if (s
.want_xday
&& !s
.have_yday
&& (s
.have_mon
|| (unsigned) tm
->tm_mon
<= 11))
1168 day_of_the_year (tm
);
1170 if ((s
.have_uweek
|| s
.have_wweek
) && s
.have_wday
)
1172 int save_wday
= tm
->tm_wday
;
1173 int save_mday
= tm
->tm_mday
;
1174 int save_mon
= tm
->tm_mon
;
1175 int w_offset
= s
.have_uweek
? 0 : 1;
1179 day_of_the_week (tm
);
1181 tm
->tm_mday
= save_mday
;
1183 tm
->tm_mon
= save_mon
;
1186 tm
->tm_yday
= ((7 - (tm
->tm_wday
- w_offset
)) % 7
1187 + (s
.week_no
- 1) * 7
1188 + (save_wday
- w_offset
+ 7) % 7);
1190 if (!s
.have_mday
|| !s
.have_mon
)
1193 while (__mon_yday
[__isleap(1900 + tm
->tm_year
)][t_mon
]
1197 tm
->tm_mon
= t_mon
- 1;
1201 - __mon_yday
[__isleap(1900 + tm
->tm_year
)][t_mon
- 1] + 1);
1204 tm
->tm_wday
= save_wday
;
1212 strptime (buf
, format
, tm LOCALE_PARAM
)
1218 return __strptime_internal (buf
, format
, tm
, NULL LOCALE_ARG
);
1222 weak_alias (__strptime_l
, strptime_l
)