1 /* strptime - Convert a string representation of time to a time value.
2 Copyright (C) 1996 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C Library 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 GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If
18 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
27 #include "../locale/localeinfo.h"
30 #define match_char(ch1, ch2) if (ch1 != ch2) return NULL
31 #define match_string(cs1, s2) \
32 ({ size_t len = strlen (cs1); \
33 int result = strncasecmp (cs1, s2, len) == 0; \
34 if (result) s2 += len; \
36 /* We intentionally do not use isdigit() for testing because this will
37 lead to problems with the wide character version. */
38 #define get_number(from, to) \
41 if (*rp < '0' || *rp > '9') \
46 } while (val * 10 <= to && *rp >= '0' && *rp <= '9'); \
47 if (val < from || val > to) \
50 #define get_alt_number(from, to) \
52 const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS); \
54 while (*alts != '\0') \
56 size_t len = strlen (alts); \
57 if (strncasecmp (alts, rp, len) == 0) \
59 alts = strchr (alts, '\0') + 1; \
65 #define recursive(new_fmt) \
67 if (*new_fmt == '\0') \
69 rp = strptime (rp, new_fmt, tm); \
76 strptime (const char *buf
, const char *format
, struct tm
*tm
)
90 /* A white space in the format string matches 0 more or white
91 space in the input string. */
100 /* Any character but `%' must be matched by the same character
101 in the iput string. */
104 match_char (*fmt
++, *rp
++);
112 /* Match the `%' character itself. */
113 match_char ('%', *rp
++);
117 /* Match day of week. */
118 for (cnt
= 0; cnt
< 7; ++cnt
)
120 if (match_string (_NL_CURRENT (LC_TIME
, ABDAY_1
+ cnt
), rp
))
122 if (match_string (_NL_CURRENT (LC_TIME
, DAY_1
+ cnt
), rp
))
126 /* Does not match a weekday name. */
133 /* Match month name. */
134 for (cnt
= 0; cnt
< 12; ++cnt
)
136 if (match_string (_NL_CURRENT (LC_TIME
, ABMON_1
+ cnt
), rp
))
138 if (match_string (_NL_CURRENT (LC_TIME
, MON_1
+ cnt
), rp
))
142 /* Does not match a month name. */
147 /* Match locale's date and time format. */
148 recursive (_NL_CURRENT (LC_TIME
, D_T_FMT
));
151 /* Match century number. */
153 /* We don't need the number. */
157 /* Match day of month. */
162 /* Match standard day format. */
163 recursive ("%m/%d/%y");
166 /* Match hour in 24-hour clock. */
172 /* Match hour in 12-hour clock. */
174 tm
->tm_hour
= val
- 1;
178 /* Match day number of year. */
180 tm
->tm_yday
= val
- 1;
183 /* Match number of month. */
185 tm
->tm_mon
= val
- 1;
194 /* Match any white space. */
195 while (isspace (*rp
))
199 /* Match locale's equivalent of AM/PM. */
200 if (match_string (_NL_CURRENT (LC_TIME
, AM_STR
), rp
))
202 if (match_string (_NL_CURRENT (LC_TIME
, PM_STR
), rp
))
209 recursive (_NL_CURRENT (LC_TIME
, T_FMT_AMPM
));
219 recursive ("%H:%M:%S");
225 /* XXX This cannot determine any field in TM. */
228 /* Match number of weekday. */
233 recursive (_NL_CURRENT (LC_TIME
, D_FMT
));
236 recursive (_NL_CURRENT (LC_TIME
, T_FMT
));
239 /* Match year within century. */
244 /* Match year including century number. */
245 get_number (0, INT_MAX
);
246 tm
->tm_year
= val
- (val
>= 2000 ? 2000 : 1900);
249 /* XXX How to handle this? */
255 /* Match locale's alternate date and time format. */
256 recursive (_NL_CURRENT (LC_TIME
, ERA_D_T_FMT
));
261 /* Match name of base year in locale's alternate
263 /* XXX This is currently not implemented. It should
264 use the value _NL_CURRENT (LC_TIME, ERA) but POSIX
265 leaves this implementation defined and we haven't
266 figured out how to do it yet. */
269 recursive (_NL_CURRENT (LC_TIME
, ERA_D_FMT
));
272 recursive (_NL_CURRENT (LC_TIME
, ERA_T_FMT
));
283 /* Match day of month using alternate numeric symbols. */
284 get_alt_number (1, 31);
288 /* Match hour in 24-hour clock using alternate numeric
290 get_alt_number (0, 23);
295 /* Match hour in 12-hour clock using alternate numeric
297 get_alt_number (1, 12);
298 tm
->tm_hour
= val
- 1;
302 /* Match month using alternate numeric symbols. */
303 get_alt_number (1, 12);
304 tm
->tm_mon
= val
- 1;
307 /* Match minutes using alternate numeric symbols. */
308 get_alt_number (0, 59);
312 /* Match seconds using alternate numeric symbols. */
313 get_alt_number (0, 61);
319 get_alt_number (0, 53);
320 /* XXX This cannot determine any field in TM. */
323 /* Match number of weekday using alternate numeric symbols. */
324 get_alt_number (0, 6);
328 /* Match year within century using alternate numeric symbols. */
329 get_alt_number (0, 99);