strptime.c revision 28019
1/*
2 * Copyright (c) 1994 Powerdog Industries.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer
11 *    in the documentation and/or other materials provided with the
12 *    distribution.
13 * 3. All advertising materials mentioning features or use of this
14 *    software must display the following acknowledgement:
15 *      This product includes software developed by Powerdog Industries.
16 * 4. The name of Powerdog Industries may not be used to endorse or
17 *    promote products derived from this software without specific prior
18 *    written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#ifndef lint
34static char copyright[] =
35"@(#) Copyright (c) 1994 Powerdog Industries.  All rights reserved.";
36static char sccsid[] = "@(#)strptime.c  0.1 (Powerdog) 94/03/27";
37#endif /* not lint */
38
39#include <time.h>
40#include <ctype.h>
41#include <locale.h>
42#include <string.h>
43
44#define asizeof(a)      (sizeof (a) / sizeof ((a)[0]))
45
46/* #ifndef sun */
47struct dtconv {
48        char    *abbrev_month_names[12];
49        char    *month_names[12];
50        char    *abbrev_weekday_names[7];
51        char    *weekday_names[7];
52        char    *time_format;
53        char    *sdate_format;
54        char    *dtime_format;
55        char    *am_string;
56        char    *pm_string;
57        char    *ldate_format;
58};
59/* #endif */
60
61static struct dtconv    En_US = {
62        { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
63          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" },
64        { "January", "February", "March", "April",
65          "May", "June", "July", "August",
66          "September", "October", "November", "December" },
67        { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" },
68        { "Sunday", "Monday", "Tuesday", "Wednesday",
69          "Thursday", "Friday", "Saturday" },
70        "%H:%M:%S",
71        "%m/%d/%y",
72        "%a %b %e %T %Z %Y",
73        "AM",
74        "PM",
75        "%A, %B, %e, %Y"
76};
77
78#ifdef SUNOS4
79extern int      strncasecmp();
80#endif
81
82char    *
83strptime(char *buf, char *fmt, struct tm *tm)
84{
85        char    c,
86                *ptr;
87        int     i,
88                len;
89
90        ptr = fmt;
91        while (*ptr != 0) {
92                if (*buf == 0)
93                        break;
94
95                c = *ptr++;
96
97                if (c != '%') {
98                        if (isspace(c))
99                                while (*buf != 0 && isspace(*buf))
100                                        buf++;
101                        else if (c != *buf++)
102                                return 0;
103                        continue;
104                }
105
106                c = *ptr++;
107                switch (c) {
108                case 0:
109                case '%':
110                        if (*buf++ != '%')
111                                return 0;
112                        break;
113
114                case 'C':
115                        buf = strptime(buf, En_US.ldate_format, tm);
116                        if (buf == 0)
117                                return 0;
118                        break;
119
120                case 'c':
121                        buf = strptime(buf, "%x %X", tm);
122                        if (buf == 0)
123                                return 0;
124                        break;
125
126                case 'D':
127                        buf = strptime(buf, "%m/%d/%y", tm);
128                        if (buf == 0)
129                                return 0;
130                        break;
131
132                case 'R':
133                        buf = strptime(buf, "%H:%M", tm);
134                        if (buf == 0)
135                                return 0;
136                        break;
137
138                case 'r':
139                        buf = strptime(buf, "%I:%M:%S %p", tm);
140                        if (buf == 0)
141                                return 0;
142                        break;
143
144                case 'T':
145                        buf = strptime(buf, "%H:%M:%S", tm);
146                        if (buf == 0)
147                                return 0;
148                        break;
149
150                case 'X':
151                        buf = strptime(buf, En_US.time_format, tm);
152                        if (buf == 0)
153                                return 0;
154                        break;
155
156                case 'x':
157                        buf = strptime(buf, En_US.sdate_format, tm);
158                        if (buf == 0)
159                                return 0;
160                        break;
161
162                case 'j':
163                        if (!isdigit(*buf))
164                                return 0;
165
166                        for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
167                                i *= 10;
168                                i += *buf - '0';
169                        }
170                        if (i > 365)
171                                return 0;
172
173                        tm->tm_yday = i;
174                        break;
175
176                case 'M':
177                case 'S':
178                        if (*buf == 0 || isspace(*buf))
179                                break;
180
181                        if (!isdigit(*buf))
182                                return 0;
183
184                        for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
185                                i *= 10;
186                                i += *buf - '0';
187                        }
188                        if (i > 59)
189                                return 0;
190
191                        if (c == 'M')
192                                tm->tm_min = i;
193                        else
194                                tm->tm_sec = i;
195
196                        if (*buf != 0 && isspace(*buf))
197                                while (*ptr != 0 && !isspace(*ptr))
198                                        ptr++;
199                        break;
200
201                case 'H':
202                case 'I':
203                case 'k':
204                case 'l':
205                        if (!isdigit(*buf))
206                                return 0;
207
208                        for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
209                                i *= 10;
210                                i += *buf - '0';
211                        }
212                        if (c == 'H' || c == 'k') {
213                                if (i > 23)
214                                        return 0;
215                        } else if (i > 11)
216                                return 0;
217
218                        tm->tm_hour = i;
219
220                        if (*buf != 0 && isspace(*buf))
221                                while (*ptr != 0 && !isspace(*ptr))
222                                        ptr++;
223                        break;
224
225                case 'p':
226                        len = strlen(En_US.am_string);
227                        if (strncasecmp(buf, En_US.am_string, len) == 0) {
228                                if (tm->tm_hour > 12)
229                                        return 0;
230                                if (tm->tm_hour == 12)
231                                        tm->tm_hour = 0;
232                                buf += len;
233                                break;
234                        }
235
236                        len = strlen(En_US.pm_string);
237                        if (strncasecmp(buf, En_US.pm_string, len) == 0) {
238                                if (tm->tm_hour > 12)
239                                        return 0;
240                                if (tm->tm_hour != 12)
241                                        tm->tm_hour += 12;
242                                buf += len;
243                                break;
244                        }
245
246                        return 0;
247
248                case 'A':
249                case 'a':
250                        for (i = 0; i < asizeof(En_US.weekday_names); i++) {
251                                len = strlen(En_US.weekday_names[i]);
252                                if (strncasecmp(buf,
253                                                En_US.weekday_names[i],
254                                                len) == 0)
255                                        break;
256
257                                len = strlen(En_US.abbrev_weekday_names[i]);
258                                if (strncasecmp(buf,
259                                                En_US.abbrev_weekday_names[i],
260                                                len) == 0)
261                                        break;
262                        }
263                        if (i == asizeof(En_US.weekday_names))
264                                return 0;
265
266                        tm->tm_wday = i;
267                        buf += len;
268                        break;
269
270                case 'd':
271                case 'e':
272                        if (!isdigit(*buf))
273                                return 0;
274
275                        for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
276                                i *= 10;
277                                i += *buf - '0';
278                        }
279                        if (i > 31)
280                                return 0;
281
282                        tm->tm_mday = i;
283
284                        if (*buf != 0 && isspace(*buf))
285                                while (*ptr != 0 && !isspace(*ptr))
286                                        ptr++;
287                        break;
288
289                case 'B':
290                case 'b':
291                case 'h':
292                        for (i = 0; i < asizeof(En_US.month_names); i++) {
293                                len = strlen(En_US.month_names[i]);
294                                if (strncasecmp(buf,
295                                                En_US.month_names[i],
296                                                len) == 0)
297                                        break;
298
299                                len = strlen(En_US.abbrev_month_names[i]);
300                                if (strncasecmp(buf,
301                                                En_US.abbrev_month_names[i],
302                                                len) == 0)
303                                        break;
304                        }
305                        if (i == asizeof(En_US.month_names))
306                                return 0;
307
308                        tm->tm_mon = i;
309                        buf += len;
310                        break;
311
312                case 'm':
313                        if (!isdigit(*buf))
314                                return 0;
315
316                        for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
317                                i *= 10;
318                                i += *buf - '0';
319                        }
320                        if (i < 1 || i > 12)
321                                return 0;
322
323                        tm->tm_mon = i - 1;
324
325                        if (*buf != 0 && isspace(*buf))
326                                while (*ptr != 0 && !isspace(*ptr))
327                                        ptr++;
328                        break;
329
330                case 'Y':
331                case 'y':
332                        if (*buf == 0 || isspace(*buf))
333                                break;
334
335                        if (!isdigit(*buf))
336                                return 0;
337
338                        for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
339                                i *= 10;
340                                i += *buf - '0';
341                        }
342                        if (c == 'Y')
343                                i -= 1900;
344                        if (i < 0)
345                                return 0;
346
347                        tm->tm_year = i;
348
349                        if (*buf != 0 && isspace(*buf))
350                                while (*ptr != 0 && !isspace(*ptr))
351                                        ptr++;
352                        break;
353                }
354        }
355
356        return buf;
357}
358
359