strptime.c revision 46051
11558Srgrimes/* 21558Srgrimes * Powerdog Industries kindly requests feedback from anyone modifying 31558Srgrimes * this function: 41558Srgrimes * 51558Srgrimes * Date: Thu, 05 Jun 1997 23:17:17 -0400 61558Srgrimes * From: Kevin Ruddy <kevin.ruddy@powerdog.com> 71558Srgrimes * To: James FitzGibbon <james@nexis.net> 81558Srgrimes * Subject: Re: Use of your strptime(3) code (fwd) 91558Srgrimes * 101558Srgrimes * The reason for the "no mod" clause was so that modifications would 111558Srgrimes * come back and we could integrate them and reissue so that a wider 121558Srgrimes * audience could use it (thereby spreading the wealth). This has 131558Srgrimes * made it possible to get strptime to work on many operating systems. 141558Srgrimes * I'm not sure why that's "plain unacceptable" to the FreeBSD team. 151558Srgrimes * 161558Srgrimes * Anyway, you can change it to "with or without modification" as 171558Srgrimes * you see fit. Enjoy. 181558Srgrimes * 191558Srgrimes * Kevin Ruddy 201558Srgrimes * Powerdog Industries, Inc. 211558Srgrimes */ 221558Srgrimes/* 231558Srgrimes * Copyright (c) 1994 Powerdog Industries. All rights reserved. 241558Srgrimes * 251558Srgrimes * Redistribution and use in source and binary forms, with or without 261558Srgrimes * modification, are permitted provided that the following conditions 271558Srgrimes * are met: 281558Srgrimes * 1. Redistributions of source code must retain the above copyright 291558Srgrimes * notice, this list of conditions and the following disclaimer. 30114589Sobrien * 2. Redistributions in binary form must reproduce the above copyright 311558Srgrimes * notice, this list of conditions and the following disclaimer 3238040Scharnier * in the documentation and/or other materials provided with the 331558Srgrimes * distribution. 341558Srgrimes * 3. All advertising materials mentioning features or use of this 351558Srgrimes * software must display the following acknowledgement: 361558Srgrimes * This product includes software developed by Powerdog Industries. 371558Srgrimes * 4. The name of Powerdog Industries may not be used to endorse or 381558Srgrimes * promote products derived from this software without specific prior 39114589Sobrien * written permission. 4038040Scharnier * 41114589Sobrien * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY 42114589Sobrien * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 431558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 441558Srgrimes * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE 45102231Strhodes * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 461558Srgrimes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 471558Srgrimes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 4842873Sluoqi * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 4996478Sphk * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 501558Srgrimes * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 511558Srgrimes * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5298542Smckusick */ 5398542Smckusick 541558Srgrimes#ifdef LIBC_RCS 55207141Sjeffstatic const char rcsid[] = 561558Srgrimes "$Id: strptime.c,v 1.5 1999/04/25 01:42:18 wes Exp $"; 57110174Sgordon#endif 581558Srgrimes 591558Srgrimes#ifndef lint 601558Srgrimes#ifndef NOID 61109597Sjmallettstatic char copyright[] = 6238040Scharnier"@(#) Copyright (c) 1994 Powerdog Industries. All rights reserved."; 631558Srgrimesstatic char sccsid[] = "@(#)strptime.c 0.1 (Powerdog) 94/03/27"; 641558Srgrimes#endif /* !defined NOID */ 65207141Sjeff#endif /* not lint */ 6658047Ssheldonh 671558Srgrimes#include <time.h> 681558Srgrimes#include <ctype.h> 691558Srgrimes#include <string.h> 701558Srgrimes#include "timelocal.h" 711558Srgrimes 72109597Sjmallett#define asizeof(a) (sizeof (a) / sizeof ((a)[0])) 73109597Sjmallett 741558Srgrimeschar * 7592883Simpstrptime(const char *buf, const char *fmt, struct tm *tm) 7692883Simp{ 77207141Sjeff char c; 78207141Sjeff const char *ptr; 79207141Sjeff int i, 801558Srgrimes len; 811558Srgrimes 82109597Sjmallett ptr = fmt; 831558Srgrimes while (*ptr != 0) { 84207141Sjeff if (*buf == 0) 85109963Sjmallett break; 8679750Sdd 87127455Sbde c = *ptr++; 88207141Sjeff 89207141Sjeff if (c != '%') { 90207141Sjeff if (isspace((unsigned char)c)) 91127441Sbde while (*buf != 0 && isspace((unsigned char)*buf)) 9279750Sdd buf++; 9342873Sluoqi else if (c != *buf++) 9442873Sluoqi return 0; 951558Srgrimes continue; 96127441Sbde } 97127441Sbde 98207141Sjeff c = *ptr++; 99207141Sjeff switch (c) { 100207141Sjeff case 0: 101207141Sjeff case '%': 102127455Sbde if (*buf++ != '%') 103127441Sbde return 0; 104207141Sjeff break; 105127441Sbde 106127441Sbde case 'C': 107127441Sbde buf = strptime(buf, Locale->date_fmt, tm); 108127441Sbde if (buf == 0) 109127441Sbde return 0; 110127441Sbde break; 111127441Sbde 112127441Sbde case 'c': 113127441Sbde buf = strptime(buf, "%x %X", tm); 114200796Strasz if (buf == 0) 115127441Sbde return 0; 116127441Sbde break; 117127441Sbde 118127441Sbde case 'D': 119127441Sbde buf = strptime(buf, "%m/%d/%y", tm); 120127441Sbde if (buf == 0) 121127441Sbde return 0; 122127441Sbde break; 123127441Sbde 124127441Sbde case 'R': 125127441Sbde buf = strptime(buf, "%H:%M", tm); 126127441Sbde if (buf == 0) 127127441Sbde return 0; 128127441Sbde break; 129127441Sbde 130127441Sbde case 'r': 131127441Sbde buf = strptime(buf, "%I:%M:%S %p", tm); 132127441Sbde if (buf == 0) 133127441Sbde return 0; 134127441Sbde break; 135127441Sbde 136127441Sbde case 'T': 137127441Sbde buf = strptime(buf, "%H:%M:%S", tm); 138127441Sbde if (buf == 0) 139127441Sbde return 0; 140127441Sbde break; 141127441Sbde 142127441Sbde case 'X': 143127441Sbde buf = strptime(buf, Locale->X_fmt, tm); 144207141Sjeff if (buf == 0) 145207141Sjeff return 0; 146207141Sjeff break; 147207141Sjeff 148207141Sjeff case 'x': 149207141Sjeff buf = strptime(buf, Locale->x_fmt, tm); 150207141Sjeff if (buf == 0) 151207141Sjeff return 0; 152207141Sjeff break; 153207141Sjeff 154207141Sjeff case 'j': 155207141Sjeff if (!isdigit((unsigned char)*buf)) 156163842Spjd return 0; 157163842Spjd 158163842Spjd for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 159163842Spjd i *= 10; 160163842Spjd i += *buf - '0'; 161163842Spjd } 162163842Spjd if (i > 365) 163163842Spjd return 0; 164163842Spjd 165163842Spjd tm->tm_yday = i; 166163842Spjd break; 167163842Spjd 168163842Spjd case 'M': 169127441Sbde case 'S': 170127441Sbde if (*buf == 0 || isspace((unsigned char)*buf)) 171127441Sbde break; 172127441Sbde 173127441Sbde if (!isdigit((unsigned char)*buf)) 174127441Sbde return 0; 175127441Sbde 176127441Sbde for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 177127441Sbde i *= 10; 178127441Sbde i += *buf - '0'; 179127441Sbde } 180127441Sbde if (i > 59) 181127441Sbde return 0; 182127441Sbde 183127441Sbde if (c == 'M') 184127441Sbde tm->tm_min = i; 185127441Sbde else 186127441Sbde tm->tm_sec = i; 187127441Sbde 188127441Sbde if (*buf != 0 && isspace((unsigned char)*buf)) 189127441Sbde while (*ptr != 0 && !isspace((unsigned char)*ptr)) 190127441Sbde ptr++; 191127441Sbde break; 192127441Sbde 193127441Sbde case 'H': 194127441Sbde case 'I': 195127441Sbde case 'k': 196127441Sbde case 'l': 197127441Sbde if (!isdigit((unsigned char)*buf)) 198127441Sbde return 0; 199127441Sbde 200127441Sbde for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 201127441Sbde i *= 10; 202127441Sbde i += *buf - '0'; 203127441Sbde } 204127441Sbde if (c == 'H' || c == 'k') { 205127441Sbde if (i > 23) 206127441Sbde return 0; 207127441Sbde } else if (i > 11) 208200796Strasz return 0; 209200796Strasz 210200796Strasz tm->tm_hour = i; 211200796Strasz 212200796Strasz if (*buf != 0 && isspace((unsigned char)*buf)) 213200796Strasz while (*ptr != 0 && !isspace((unsigned char)*ptr)) 214200796Strasz ptr++; 215200796Strasz break; 216200796Strasz 217200796Strasz case 'p': 218200796Strasz len = strlen(Locale->am); 219200796Strasz if (strncasecmp(buf, Locale->am, len) == 0) { 220127441Sbde if (tm->tm_hour > 12) 221127441Sbde return 0; 222127441Sbde if (tm->tm_hour == 12) 223127441Sbde tm->tm_hour = 0; 224127455Sbde buf += len; 225127455Sbde break; 226127441Sbde } 227127441Sbde 228127441Sbde len = strlen(Locale->pm); 229127441Sbde if (strncasecmp(buf, Locale->pm, len) == 0) { 230127441Sbde if (tm->tm_hour > 12) 231127441Sbde return 0; 232127441Sbde if (tm->tm_hour != 12) 233127441Sbde tm->tm_hour += 12; 234127441Sbde buf += len; 235127455Sbde break; 236127441Sbde } 237127455Sbde 238127441Sbde return 0; 239127441Sbde 240127441Sbde case 'A': 241127441Sbde case 'a': 242127441Sbde for (i = 0; i < asizeof(Locale->weekday); i++) { 243127441Sbde len = strlen(Locale->weekday[i]); 244127441Sbde if (strncasecmp(buf, 245127441Sbde Locale->weekday[i], 246127441Sbde len) == 0) 247127441Sbde break; 248127441Sbde 249127441Sbde len = strlen(Locale->wday[i]); 250127441Sbde if (strncasecmp(buf, 251127441Sbde Locale->wday[i], 252127441Sbde len) == 0) 253127441Sbde break; 254127441Sbde } 255127441Sbde if (i == asizeof(Locale->weekday)) 256127441Sbde return 0; 257127441Sbde 258127441Sbde tm->tm_wday = i; 259127441Sbde buf += len; 260127441Sbde break; 261207141Sjeff 262207141Sjeff case 'd': 263207141Sjeff case 'e': 264207141Sjeff if (!isdigit((unsigned char)*buf)) 265207141Sjeff return 0; 266207141Sjeff 267207141Sjeff for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 268207141Sjeff i *= 10; 269207141Sjeff i += *buf - '0'; 270207141Sjeff } 271127441Sbde if (i > 31) 272127441Sbde return 0; 273105120Srwatson 27469314Scharnier tm->tm_mday = i; 27569314Scharnier 27669314Scharnier if (*buf != 0 && isspace((unsigned char)*buf)) 277127441Sbde while (*ptr != 0 && !isspace((unsigned char)*ptr)) 27869314Scharnier ptr++; 279109963Sjmallett break; 280109963Sjmallett 281109963Sjmallett case 'B': 282109963Sjmallett case 'b': 283207421Sjeff case 'h': 284207421Sjeff for (i = 0; i < asizeof(Locale->month); i++) { 285207421Sjeff len = strlen(Locale->month[i]); 28669829Scharnier if (strncasecmp(buf, 28769829Scharnier Locale->month[i], 28869829Scharnier len) == 0) 28969829Scharnier break; 29069829Scharnier 29169829Scharnier len = strlen(Locale->mon[i]); 29269829Scharnier if (strncasecmp(buf, 293110174Sgordon Locale->mon[i], 294110174Sgordon len) == 0) 295110174Sgordon break; 296110174Sgordon } 297105120Srwatson if (i == asizeof(Locale->month)) 298200796Strasz return 0; 299105120Srwatson 300105120Srwatson tm->tm_mon = i; 301105120Srwatson buf += len; 302200796Strasz break; 303200796Strasz 304200796Strasz case 'm': 305105120Srwatson if (!isdigit((unsigned char)*buf)) 306105120Srwatson return 0; 307105120Srwatson 308105120Srwatson for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 309105120Srwatson i *= 10; 310105120Srwatson i += *buf - '0'; 311105120Srwatson } 312105120Srwatson if (i < 1 || i > 12) 313105120Srwatson return 0; 314105120Srwatson 315105120Srwatson tm->tm_mon = i - 1; 316105206Srwatson 317105120Srwatson if (*buf != 0 && isspace((unsigned char)*buf)) 318105120Srwatson while (*ptr != 0 && !isspace((unsigned char)*ptr)) 319105120Srwatson ptr++; 32069829Scharnier break; 32169829Scharnier 322127455Sbde case 'Y': 32369829Scharnier case 'y': 32469829Scharnier if (*buf == 0 || isspace((unsigned char)*buf)) 32569829Scharnier break; 326127455Sbde 32769829Scharnier if (!isdigit((unsigned char)*buf)) 32869829Scharnier return 0; 32969829Scharnier 33075377Smckusick for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { 33175377Smckusick i *= 10; 332203769Smckusick i += *buf - '0'; 33375377Smckusick } 33475377Smckusick if (c == 'Y') 33575377Smckusick i -= 1900; 33675377Smckusick if (c == 'y' && i < 69) 33775377Smckusick i += 100; 33875377Smckusick if (i < 0) 33975377Smckusick return 0; 34075377Smckusick 341207141Sjeff tm->tm_year = i; 342207141Sjeff 343207141Sjeff if (*buf != 0 && isspace((unsigned char)*buf)) 344207141Sjeff while (*ptr != 0 && !isspace((unsigned char)*ptr)) 345207141Sjeff ptr++; 346207141Sjeff break; 347207141Sjeff } 348207141Sjeff } 349207141Sjeff 350207141Sjeff return (char *)buf; 351207141Sjeff} 352207141Sjeff