strptime.c revision 28019
128019Sjoerg/*
228019Sjoerg * Copyright (c) 1994 Powerdog Industries.  All rights reserved.
328019Sjoerg *
428019Sjoerg * Redistribution and use in source and binary forms, without
528019Sjoerg * modification, are permitted provided that the following conditions
628019Sjoerg * are met:
728019Sjoerg * 1. Redistributions of source code must retain the above copyright
828019Sjoerg *    notice, this list of conditions and the following disclaimer.
928019Sjoerg * 2. Redistributions in binary form must reproduce the above copyright
1028019Sjoerg *    notice, this list of conditions and the following disclaimer
1128019Sjoerg *    in the documentation and/or other materials provided with the
1228019Sjoerg *    distribution.
1328019Sjoerg * 3. All advertising materials mentioning features or use of this
1428019Sjoerg *    software must display the following acknowledgement:
1528019Sjoerg *      This product includes software developed by Powerdog Industries.
1628019Sjoerg * 4. The name of Powerdog Industries may not be used to endorse or
1728019Sjoerg *    promote products derived from this software without specific prior
1828019Sjoerg *    written permission.
1928019Sjoerg *
2028019Sjoerg * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY
2128019Sjoerg * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2228019Sjoerg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2328019Sjoerg * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE
2428019Sjoerg * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2528019Sjoerg * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2628019Sjoerg * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
2728019Sjoerg * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2828019Sjoerg * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
2928019Sjoerg * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
3028019Sjoerg * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3128019Sjoerg */
3228019Sjoerg
3328019Sjoerg#ifndef lint
3428019Sjoergstatic char copyright[] =
3528019Sjoerg"@(#) Copyright (c) 1994 Powerdog Industries.  All rights reserved.";
3628019Sjoergstatic char sccsid[] = "@(#)strptime.c  0.1 (Powerdog) 94/03/27";
3728019Sjoerg#endif /* not lint */
3828019Sjoerg
3928019Sjoerg#include <time.h>
4028019Sjoerg#include <ctype.h>
4128019Sjoerg#include <locale.h>
4228019Sjoerg#include <string.h>
4328019Sjoerg
4428019Sjoerg#define asizeof(a)      (sizeof (a) / sizeof ((a)[0]))
4528019Sjoerg
4628019Sjoerg/* #ifndef sun */
4728019Sjoergstruct dtconv {
4828019Sjoerg        char    *abbrev_month_names[12];
4928019Sjoerg        char    *month_names[12];
5028019Sjoerg        char    *abbrev_weekday_names[7];
5128019Sjoerg        char    *weekday_names[7];
5228019Sjoerg        char    *time_format;
5328019Sjoerg        char    *sdate_format;
5428019Sjoerg        char    *dtime_format;
5528019Sjoerg        char    *am_string;
5628019Sjoerg        char    *pm_string;
5728019Sjoerg        char    *ldate_format;
5828019Sjoerg};
5928019Sjoerg/* #endif */
6028019Sjoerg
6128019Sjoergstatic struct dtconv    En_US = {
6228019Sjoerg        { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
6328019Sjoerg          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" },
6428019Sjoerg        { "January", "February", "March", "April",
6528019Sjoerg          "May", "June", "July", "August",
6628019Sjoerg          "September", "October", "November", "December" },
6728019Sjoerg        { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" },
6828019Sjoerg        { "Sunday", "Monday", "Tuesday", "Wednesday",
6928019Sjoerg          "Thursday", "Friday", "Saturday" },
7028019Sjoerg        "%H:%M:%S",
7128019Sjoerg        "%m/%d/%y",
7228019Sjoerg        "%a %b %e %T %Z %Y",
7328019Sjoerg        "AM",
7428019Sjoerg        "PM",
7528019Sjoerg        "%A, %B, %e, %Y"
7628019Sjoerg};
7728019Sjoerg
7828019Sjoerg#ifdef SUNOS4
7928019Sjoergextern int      strncasecmp();
8028019Sjoerg#endif
8128019Sjoerg
8228019Sjoergchar    *
8328019Sjoergstrptime(char *buf, char *fmt, struct tm *tm)
8428019Sjoerg{
8528019Sjoerg        char    c,
8628019Sjoerg                *ptr;
8728019Sjoerg        int     i,
8828019Sjoerg                len;
8928019Sjoerg
9028019Sjoerg        ptr = fmt;
9128019Sjoerg        while (*ptr != 0) {
9228019Sjoerg                if (*buf == 0)
9328019Sjoerg                        break;
9428019Sjoerg
9528019Sjoerg                c = *ptr++;
9628019Sjoerg
9728019Sjoerg                if (c != '%') {
9828019Sjoerg                        if (isspace(c))
9928019Sjoerg                                while (*buf != 0 && isspace(*buf))
10028019Sjoerg                                        buf++;
10128019Sjoerg                        else if (c != *buf++)
10228019Sjoerg                                return 0;
10328019Sjoerg                        continue;
10428019Sjoerg                }
10528019Sjoerg
10628019Sjoerg                c = *ptr++;
10728019Sjoerg                switch (c) {
10828019Sjoerg                case 0:
10928019Sjoerg                case '%':
11028019Sjoerg                        if (*buf++ != '%')
11128019Sjoerg                                return 0;
11228019Sjoerg                        break;
11328019Sjoerg
11428019Sjoerg                case 'C':
11528019Sjoerg                        buf = strptime(buf, En_US.ldate_format, tm);
11628019Sjoerg                        if (buf == 0)
11728019Sjoerg                                return 0;
11828019Sjoerg                        break;
11928019Sjoerg
12028019Sjoerg                case 'c':
12128019Sjoerg                        buf = strptime(buf, "%x %X", tm);
12228019Sjoerg                        if (buf == 0)
12328019Sjoerg                                return 0;
12428019Sjoerg                        break;
12528019Sjoerg
12628019Sjoerg                case 'D':
12728019Sjoerg                        buf = strptime(buf, "%m/%d/%y", tm);
12828019Sjoerg                        if (buf == 0)
12928019Sjoerg                                return 0;
13028019Sjoerg                        break;
13128019Sjoerg
13228019Sjoerg                case 'R':
13328019Sjoerg                        buf = strptime(buf, "%H:%M", tm);
13428019Sjoerg                        if (buf == 0)
13528019Sjoerg                                return 0;
13628019Sjoerg                        break;
13728019Sjoerg
13828019Sjoerg                case 'r':
13928019Sjoerg                        buf = strptime(buf, "%I:%M:%S %p", tm);
14028019Sjoerg                        if (buf == 0)
14128019Sjoerg                                return 0;
14228019Sjoerg                        break;
14328019Sjoerg
14428019Sjoerg                case 'T':
14528019Sjoerg                        buf = strptime(buf, "%H:%M:%S", tm);
14628019Sjoerg                        if (buf == 0)
14728019Sjoerg                                return 0;
14828019Sjoerg                        break;
14928019Sjoerg
15028019Sjoerg                case 'X':
15128019Sjoerg                        buf = strptime(buf, En_US.time_format, tm);
15228019Sjoerg                        if (buf == 0)
15328019Sjoerg                                return 0;
15428019Sjoerg                        break;
15528019Sjoerg
15628019Sjoerg                case 'x':
15728019Sjoerg                        buf = strptime(buf, En_US.sdate_format, tm);
15828019Sjoerg                        if (buf == 0)
15928019Sjoerg                                return 0;
16028019Sjoerg                        break;
16128019Sjoerg
16228019Sjoerg                case 'j':
16328019Sjoerg                        if (!isdigit(*buf))
16428019Sjoerg                                return 0;
16528019Sjoerg
16628019Sjoerg                        for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
16728019Sjoerg                                i *= 10;
16828019Sjoerg                                i += *buf - '0';
16928019Sjoerg                        }
17028019Sjoerg                        if (i > 365)
17128019Sjoerg                                return 0;
17228019Sjoerg
17328019Sjoerg                        tm->tm_yday = i;
17428019Sjoerg                        break;
17528019Sjoerg
17628019Sjoerg                case 'M':
17728019Sjoerg                case 'S':
17828019Sjoerg                        if (*buf == 0 || isspace(*buf))
17928019Sjoerg                                break;
18028019Sjoerg
18128019Sjoerg                        if (!isdigit(*buf))
18228019Sjoerg                                return 0;
18328019Sjoerg
18428019Sjoerg                        for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
18528019Sjoerg                                i *= 10;
18628019Sjoerg                                i += *buf - '0';
18728019Sjoerg                        }
18828019Sjoerg                        if (i > 59)
18928019Sjoerg                                return 0;
19028019Sjoerg
19128019Sjoerg                        if (c == 'M')
19228019Sjoerg                                tm->tm_min = i;
19328019Sjoerg                        else
19428019Sjoerg                                tm->tm_sec = i;
19528019Sjoerg
19628019Sjoerg                        if (*buf != 0 && isspace(*buf))
19728019Sjoerg                                while (*ptr != 0 && !isspace(*ptr))
19828019Sjoerg                                        ptr++;
19928019Sjoerg                        break;
20028019Sjoerg
20128019Sjoerg                case 'H':
20228019Sjoerg                case 'I':
20328019Sjoerg                case 'k':
20428019Sjoerg                case 'l':
20528019Sjoerg                        if (!isdigit(*buf))
20628019Sjoerg                                return 0;
20728019Sjoerg
20828019Sjoerg                        for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
20928019Sjoerg                                i *= 10;
21028019Sjoerg                                i += *buf - '0';
21128019Sjoerg                        }
21228019Sjoerg                        if (c == 'H' || c == 'k') {
21328019Sjoerg                                if (i > 23)
21428019Sjoerg                                        return 0;
21528019Sjoerg                        } else if (i > 11)
21628019Sjoerg                                return 0;
21728019Sjoerg
21828019Sjoerg                        tm->tm_hour = i;
21928019Sjoerg
22028019Sjoerg                        if (*buf != 0 && isspace(*buf))
22128019Sjoerg                                while (*ptr != 0 && !isspace(*ptr))
22228019Sjoerg                                        ptr++;
22328019Sjoerg                        break;
22428019Sjoerg
22528019Sjoerg                case 'p':
22628019Sjoerg                        len = strlen(En_US.am_string);
22728019Sjoerg                        if (strncasecmp(buf, En_US.am_string, len) == 0) {
22828019Sjoerg                                if (tm->tm_hour > 12)
22928019Sjoerg                                        return 0;
23028019Sjoerg                                if (tm->tm_hour == 12)
23128019Sjoerg                                        tm->tm_hour = 0;
23228019Sjoerg                                buf += len;
23328019Sjoerg                                break;
23428019Sjoerg                        }
23528019Sjoerg
23628019Sjoerg                        len = strlen(En_US.pm_string);
23728019Sjoerg                        if (strncasecmp(buf, En_US.pm_string, len) == 0) {
23828019Sjoerg                                if (tm->tm_hour > 12)
23928019Sjoerg                                        return 0;
24028019Sjoerg                                if (tm->tm_hour != 12)
24128019Sjoerg                                        tm->tm_hour += 12;
24228019Sjoerg                                buf += len;
24328019Sjoerg                                break;
24428019Sjoerg                        }
24528019Sjoerg
24628019Sjoerg                        return 0;
24728019Sjoerg
24828019Sjoerg                case 'A':
24928019Sjoerg                case 'a':
25028019Sjoerg                        for (i = 0; i < asizeof(En_US.weekday_names); i++) {
25128019Sjoerg                                len = strlen(En_US.weekday_names[i]);
25228019Sjoerg                                if (strncasecmp(buf,
25328019Sjoerg                                                En_US.weekday_names[i],
25428019Sjoerg                                                len) == 0)
25528019Sjoerg                                        break;
25628019Sjoerg
25728019Sjoerg                                len = strlen(En_US.abbrev_weekday_names[i]);
25828019Sjoerg                                if (strncasecmp(buf,
25928019Sjoerg                                                En_US.abbrev_weekday_names[i],
26028019Sjoerg                                                len) == 0)
26128019Sjoerg                                        break;
26228019Sjoerg                        }
26328019Sjoerg                        if (i == asizeof(En_US.weekday_names))
26428019Sjoerg                                return 0;
26528019Sjoerg
26628019Sjoerg                        tm->tm_wday = i;
26728019Sjoerg                        buf += len;
26828019Sjoerg                        break;
26928019Sjoerg
27028019Sjoerg                case 'd':
27128019Sjoerg                case 'e':
27228019Sjoerg                        if (!isdigit(*buf))
27328019Sjoerg                                return 0;
27428019Sjoerg
27528019Sjoerg                        for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
27628019Sjoerg                                i *= 10;
27728019Sjoerg                                i += *buf - '0';
27828019Sjoerg                        }
27928019Sjoerg                        if (i > 31)
28028019Sjoerg                                return 0;
28128019Sjoerg
28228019Sjoerg                        tm->tm_mday = i;
28328019Sjoerg
28428019Sjoerg                        if (*buf != 0 && isspace(*buf))
28528019Sjoerg                                while (*ptr != 0 && !isspace(*ptr))
28628019Sjoerg                                        ptr++;
28728019Sjoerg                        break;
28828019Sjoerg
28928019Sjoerg                case 'B':
29028019Sjoerg                case 'b':
29128019Sjoerg                case 'h':
29228019Sjoerg                        for (i = 0; i < asizeof(En_US.month_names); i++) {
29328019Sjoerg                                len = strlen(En_US.month_names[i]);
29428019Sjoerg                                if (strncasecmp(buf,
29528019Sjoerg                                                En_US.month_names[i],
29628019Sjoerg                                                len) == 0)
29728019Sjoerg                                        break;
29828019Sjoerg
29928019Sjoerg                                len = strlen(En_US.abbrev_month_names[i]);
30028019Sjoerg                                if (strncasecmp(buf,
30128019Sjoerg                                                En_US.abbrev_month_names[i],
30228019Sjoerg                                                len) == 0)
30328019Sjoerg                                        break;
30428019Sjoerg                        }
30528019Sjoerg                        if (i == asizeof(En_US.month_names))
30628019Sjoerg                                return 0;
30728019Sjoerg
30828019Sjoerg                        tm->tm_mon = i;
30928019Sjoerg                        buf += len;
31028019Sjoerg                        break;
31128019Sjoerg
31228019Sjoerg                case 'm':
31328019Sjoerg                        if (!isdigit(*buf))
31428019Sjoerg                                return 0;
31528019Sjoerg
31628019Sjoerg                        for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
31728019Sjoerg                                i *= 10;
31828019Sjoerg                                i += *buf - '0';
31928019Sjoerg                        }
32028019Sjoerg                        if (i < 1 || i > 12)
32128019Sjoerg                                return 0;
32228019Sjoerg
32328019Sjoerg                        tm->tm_mon = i - 1;
32428019Sjoerg
32528019Sjoerg                        if (*buf != 0 && isspace(*buf))
32628019Sjoerg                                while (*ptr != 0 && !isspace(*ptr))
32728019Sjoerg                                        ptr++;
32828019Sjoerg                        break;
32928019Sjoerg
33028019Sjoerg                case 'Y':
33128019Sjoerg                case 'y':
33228019Sjoerg                        if (*buf == 0 || isspace(*buf))
33328019Sjoerg                                break;
33428019Sjoerg
33528019Sjoerg                        if (!isdigit(*buf))
33628019Sjoerg                                return 0;
33728019Sjoerg
33828019Sjoerg                        for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
33928019Sjoerg                                i *= 10;
34028019Sjoerg                                i += *buf - '0';
34128019Sjoerg                        }
34228019Sjoerg                        if (c == 'Y')
34328019Sjoerg                                i -= 1900;
34428019Sjoerg                        if (i < 0)
34528019Sjoerg                                return 0;
34628019Sjoerg
34728019Sjoerg                        tm->tm_year = i;
34828019Sjoerg
34928019Sjoerg                        if (*buf != 0 && isspace(*buf))
35028019Sjoerg                                while (*ptr != 0 && !isspace(*ptr))
35128019Sjoerg                                        ptr++;
35228019Sjoerg                        break;
35328019Sjoerg                }
35428019Sjoerg        }
35528019Sjoerg
35628019Sjoerg        return buf;
35728019Sjoerg}
35828019Sjoerg
359