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