strptime.c revision 46051
128019Sjoerg/* 228021Sjoerg * Powerdog Industries kindly requests feedback from anyone modifying 328021Sjoerg * this function: 428021Sjoerg * 528021Sjoerg * Date: Thu, 05 Jun 1997 23:17:17 -0400 628021Sjoerg * From: Kevin Ruddy <kevin.ruddy@powerdog.com> 728021Sjoerg * To: James FitzGibbon <james@nexis.net> 828021Sjoerg * Subject: Re: Use of your strptime(3) code (fwd) 928021Sjoerg * 1028021Sjoerg * The reason for the "no mod" clause was so that modifications would 1128021Sjoerg * come back and we could integrate them and reissue so that a wider 1228021Sjoerg * audience could use it (thereby spreading the wealth). This has 1328021Sjoerg * made it possible to get strptime to work on many operating systems. 1428021Sjoerg * I'm not sure why that's "plain unacceptable" to the FreeBSD team. 1528021Sjoerg * 1628021Sjoerg * Anyway, you can change it to "with or without modification" as 1728021Sjoerg * you see fit. Enjoy. 1828021Sjoerg * 1928021Sjoerg * Kevin Ruddy 2028021Sjoerg * Powerdog Industries, Inc. 2128021Sjoerg */ 2228021Sjoerg/* 2328019Sjoerg * Copyright (c) 1994 Powerdog Industries. All rights reserved. 2428019Sjoerg * 2528021Sjoerg * Redistribution and use in source and binary forms, with or without 2628019Sjoerg * modification, are permitted provided that the following conditions 2728019Sjoerg * are met: 2828019Sjoerg * 1. Redistributions of source code must retain the above copyright 2928019Sjoerg * notice, this list of conditions and the following disclaimer. 3028019Sjoerg * 2. Redistributions in binary form must reproduce the above copyright 3128019Sjoerg * notice, this list of conditions and the following disclaimer 3228019Sjoerg * in the documentation and/or other materials provided with the 3328019Sjoerg * distribution. 3428019Sjoerg * 3. All advertising materials mentioning features or use of this 3528019Sjoerg * software must display the following acknowledgement: 3628019Sjoerg * This product includes software developed by Powerdog Industries. 3728019Sjoerg * 4. The name of Powerdog Industries may not be used to endorse or 3828019Sjoerg * promote products derived from this software without specific prior 3928019Sjoerg * written permission. 4028019Sjoerg * 4128019Sjoerg * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY 4228019Sjoerg * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4328019Sjoerg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4428019Sjoerg * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE 4528019Sjoerg * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 4628019Sjoerg * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 4728019Sjoerg * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 4828019Sjoerg * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 4928019Sjoerg * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 5028019Sjoerg * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 5128019Sjoerg * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5228019Sjoerg */ 5328019Sjoerg 5428021Sjoerg#ifdef LIBC_RCS 5528021Sjoergstatic const char rcsid[] = 5646051Swes "$Id: strptime.c,v 1.5 1999/04/25 01:42:18 wes Exp $"; 5728021Sjoerg#endif 5828021Sjoerg 5928019Sjoerg#ifndef lint 6028021Sjoerg#ifndef NOID 6128019Sjoergstatic char copyright[] = 6228019Sjoerg"@(#) Copyright (c) 1994 Powerdog Industries. All rights reserved."; 6328021Sjoergstatic char sccsid[] = "@(#)strptime.c 0.1 (Powerdog) 94/03/27"; 6428021Sjoerg#endif /* !defined NOID */ 6528019Sjoerg#endif /* not lint */ 6628019Sjoerg 6728019Sjoerg#include <time.h> 6828019Sjoerg#include <ctype.h> 6928019Sjoerg#include <string.h> 7028021Sjoerg#include "timelocal.h" 7128019Sjoerg 7228021Sjoerg#define asizeof(a) (sizeof (a) / sizeof ((a)[0])) 7328019Sjoerg 7439113Sdtchar * 7528021Sjoergstrptime(const char *buf, const char *fmt, struct tm *tm) 7628019Sjoerg{ 7728021Sjoerg char c; 7828021Sjoerg const char *ptr; 7928021Sjoerg int i, 8028021Sjoerg len; 8128019Sjoerg 8228021Sjoerg ptr = fmt; 8328021Sjoerg while (*ptr != 0) { 8428021Sjoerg if (*buf == 0) 8528021Sjoerg break; 8628019Sjoerg 8728021Sjoerg c = *ptr++; 8828019Sjoerg 8928021Sjoerg if (c != '%') { 9028164Sache if (isspace((unsigned char)c)) 9128164Sache while (*buf != 0 && isspace((unsigned char)*buf)) 9228021Sjoerg buf++; 9328021Sjoerg else if (c != *buf++) 9428021Sjoerg return 0; 9528021Sjoerg continue; 9628021Sjoerg } 9728019Sjoerg 9828021Sjoerg c = *ptr++; 9928021Sjoerg switch (c) { 10028021Sjoerg case 0: 10128021Sjoerg case '%': 10228021Sjoerg if (*buf++ != '%') 10328021Sjoerg return 0; 10428021Sjoerg break; 10528019Sjoerg 10628021Sjoerg case 'C': 10728021Sjoerg buf = strptime(buf, Locale->date_fmt, tm); 10828021Sjoerg if (buf == 0) 10928021Sjoerg return 0; 11028021Sjoerg break; 11128019Sjoerg 11228021Sjoerg case 'c': 11328021Sjoerg buf = strptime(buf, "%x %X", tm); 11428021Sjoerg if (buf == 0) 11528021Sjoerg return 0; 11628021Sjoerg break; 11728019Sjoerg 11828021Sjoerg case 'D': 11928021Sjoerg buf = strptime(buf, "%m/%d/%y", tm); 12028021Sjoerg if (buf == 0) 12128021Sjoerg return 0; 12228021Sjoerg break; 12328019Sjoerg 12428021Sjoerg case 'R': 12528021Sjoerg buf = strptime(buf, "%H:%M", tm); 12628021Sjoerg if (buf == 0) 12728021Sjoerg return 0; 12828021Sjoerg break; 12928019Sjoerg 13028021Sjoerg case 'r': 13128021Sjoerg buf = strptime(buf, "%I:%M:%S %p", tm); 13228021Sjoerg if (buf == 0) 13328021Sjoerg return 0; 13428021Sjoerg break; 13528019Sjoerg 13628021Sjoerg case 'T': 13728021Sjoerg buf = strptime(buf, "%H:%M:%S", tm); 13828021Sjoerg if (buf == 0) 13928021Sjoerg return 0; 14028021Sjoerg break; 14128019Sjoerg 14228021Sjoerg case 'X': 14328021Sjoerg buf = strptime(buf, Locale->X_fmt, tm); 14428021Sjoerg if (buf == 0) 14528021Sjoerg return 0; 14628021Sjoerg break; 14728019Sjoerg 14828021Sjoerg case 'x': 14928021Sjoerg buf = strptime(buf, Locale->x_fmt, tm); 15028021Sjoerg if (buf == 0) 15128021Sjoerg return 0; 15228021Sjoerg break; 15328019Sjoerg 15428021Sjoerg case 'j': 15528164Sache if (!isdigit((unsigned char)*buf)) 15628021Sjoerg return 0; 15728019Sjoerg 15828164Sache for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 15928021Sjoerg i *= 10; 16028021Sjoerg i += *buf - '0'; 16128021Sjoerg } 16228021Sjoerg if (i > 365) 16328021Sjoerg return 0; 16428019Sjoerg 16528021Sjoerg tm->tm_yday = i; 16628021Sjoerg break; 16728019Sjoerg 16828021Sjoerg case 'M': 16928021Sjoerg case 'S': 17028164Sache if (*buf == 0 || isspace((unsigned char)*buf)) 17128021Sjoerg break; 17228019Sjoerg 17328164Sache if (!isdigit((unsigned char)*buf)) 17428021Sjoerg return 0; 17528019Sjoerg 17628164Sache for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 17728021Sjoerg i *= 10; 17828021Sjoerg i += *buf - '0'; 17928021Sjoerg } 18028021Sjoerg if (i > 59) 18128021Sjoerg return 0; 18228019Sjoerg 18328021Sjoerg if (c == 'M') 18428021Sjoerg tm->tm_min = i; 18528021Sjoerg else 18628021Sjoerg tm->tm_sec = i; 18728019Sjoerg 18828164Sache if (*buf != 0 && isspace((unsigned char)*buf)) 18928164Sache while (*ptr != 0 && !isspace((unsigned char)*ptr)) 19028021Sjoerg ptr++; 19128021Sjoerg break; 19228019Sjoerg 19328021Sjoerg case 'H': 19428021Sjoerg case 'I': 19528021Sjoerg case 'k': 19628021Sjoerg case 'l': 19728164Sache if (!isdigit((unsigned char)*buf)) 19828021Sjoerg return 0; 19928019Sjoerg 20028164Sache for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 20128021Sjoerg i *= 10; 20228021Sjoerg i += *buf - '0'; 20328021Sjoerg } 20428021Sjoerg if (c == 'H' || c == 'k') { 20528021Sjoerg if (i > 23) 20628021Sjoerg return 0; 20728021Sjoerg } else if (i > 11) 20828021Sjoerg return 0; 20928019Sjoerg 21028021Sjoerg tm->tm_hour = i; 21128019Sjoerg 21228164Sache if (*buf != 0 && isspace((unsigned char)*buf)) 21328164Sache while (*ptr != 0 && !isspace((unsigned char)*ptr)) 21428021Sjoerg ptr++; 21528021Sjoerg break; 21628019Sjoerg 21728021Sjoerg case 'p': 21828021Sjoerg len = strlen(Locale->am); 21928021Sjoerg if (strncasecmp(buf, Locale->am, len) == 0) { 22028021Sjoerg if (tm->tm_hour > 12) 22128021Sjoerg return 0; 22228021Sjoerg if (tm->tm_hour == 12) 22328021Sjoerg tm->tm_hour = 0; 22428021Sjoerg buf += len; 22528021Sjoerg break; 22628021Sjoerg } 22728019Sjoerg 22828021Sjoerg len = strlen(Locale->pm); 22928021Sjoerg if (strncasecmp(buf, Locale->pm, len) == 0) { 23028021Sjoerg if (tm->tm_hour > 12) 23128021Sjoerg return 0; 23228021Sjoerg if (tm->tm_hour != 12) 23328021Sjoerg tm->tm_hour += 12; 23428021Sjoerg buf += len; 23528021Sjoerg break; 23628021Sjoerg } 23728019Sjoerg 23828021Sjoerg return 0; 23928019Sjoerg 24028021Sjoerg case 'A': 24128021Sjoerg case 'a': 24228021Sjoerg for (i = 0; i < asizeof(Locale->weekday); i++) { 24328021Sjoerg len = strlen(Locale->weekday[i]); 24428021Sjoerg if (strncasecmp(buf, 24528021Sjoerg Locale->weekday[i], 24628021Sjoerg len) == 0) 24728021Sjoerg break; 24828019Sjoerg 24928021Sjoerg len = strlen(Locale->wday[i]); 25028021Sjoerg if (strncasecmp(buf, 25128021Sjoerg Locale->wday[i], 25228021Sjoerg len) == 0) 25328021Sjoerg break; 25428021Sjoerg } 25528021Sjoerg if (i == asizeof(Locale->weekday)) 25628021Sjoerg return 0; 25728019Sjoerg 25828021Sjoerg tm->tm_wday = i; 25928021Sjoerg buf += len; 26028021Sjoerg break; 26128019Sjoerg 26228021Sjoerg case 'd': 26328021Sjoerg case 'e': 26428164Sache if (!isdigit((unsigned char)*buf)) 26528021Sjoerg return 0; 26628019Sjoerg 26728164Sache for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 26828021Sjoerg i *= 10; 26928021Sjoerg i += *buf - '0'; 27028021Sjoerg } 27128021Sjoerg if (i > 31) 27228021Sjoerg return 0; 27328019Sjoerg 27428021Sjoerg tm->tm_mday = i; 27528019Sjoerg 27628164Sache if (*buf != 0 && isspace((unsigned char)*buf)) 27728164Sache while (*ptr != 0 && !isspace((unsigned char)*ptr)) 27828021Sjoerg ptr++; 27928021Sjoerg break; 28028019Sjoerg 28128021Sjoerg case 'B': 28228021Sjoerg case 'b': 28328021Sjoerg case 'h': 28428021Sjoerg for (i = 0; i < asizeof(Locale->month); i++) { 28528021Sjoerg len = strlen(Locale->month[i]); 28628021Sjoerg if (strncasecmp(buf, 28728021Sjoerg Locale->month[i], 28828021Sjoerg len) == 0) 28928021Sjoerg break; 29028019Sjoerg 29128021Sjoerg len = strlen(Locale->mon[i]); 29228021Sjoerg if (strncasecmp(buf, 29328021Sjoerg Locale->mon[i], 29428021Sjoerg len) == 0) 29528021Sjoerg break; 29628021Sjoerg } 29728021Sjoerg if (i == asizeof(Locale->month)) 29828021Sjoerg return 0; 29928019Sjoerg 30028021Sjoerg tm->tm_mon = i; 30128021Sjoerg buf += len; 30228021Sjoerg break; 30328019Sjoerg 30428021Sjoerg case 'm': 30528164Sache if (!isdigit((unsigned char)*buf)) 30628021Sjoerg return 0; 30728019Sjoerg 30828164Sache for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 30928021Sjoerg i *= 10; 31028021Sjoerg i += *buf - '0'; 31128021Sjoerg } 31228021Sjoerg if (i < 1 || i > 12) 31328021Sjoerg return 0; 31428019Sjoerg 31528021Sjoerg tm->tm_mon = i - 1; 31628019Sjoerg 31728164Sache if (*buf != 0 && isspace((unsigned char)*buf)) 31828164Sache while (*ptr != 0 && !isspace((unsigned char)*ptr)) 31928021Sjoerg ptr++; 32028021Sjoerg break; 32128019Sjoerg 32228021Sjoerg case 'Y': 32328021Sjoerg case 'y': 32428164Sache if (*buf == 0 || isspace((unsigned char)*buf)) 32528021Sjoerg break; 32628019Sjoerg 32728164Sache if (!isdigit((unsigned char)*buf)) 32828021Sjoerg return 0; 32928019Sjoerg 33028164Sache for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 33128021Sjoerg i *= 10; 33228021Sjoerg i += *buf - '0'; 33328021Sjoerg } 33428021Sjoerg if (c == 'Y') 33528021Sjoerg i -= 1900; 33646051Swes if (c == 'y' && i < 69) 33746042Swes i += 100; 33828021Sjoerg if (i < 0) 33928021Sjoerg return 0; 34028019Sjoerg 34128021Sjoerg tm->tm_year = i; 34228019Sjoerg 34328164Sache if (*buf != 0 && isspace((unsigned char)*buf)) 34428164Sache while (*ptr != 0 && !isspace((unsigned char)*ptr)) 34528021Sjoerg ptr++; 34628021Sjoerg break; 34728021Sjoerg } 34828021Sjoerg } 34928019Sjoerg 35039113Sdt return (char *)buf; 35128019Sjoerg} 352