File indexing completed on 2025-08-03 08:20:42
0001 #ifndef __STRPTIME_C__
0002 #define __STRPTIME_C__
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 extern "C"
0036 {
0037
0038 #ifndef HAVE_STRPTIME_PROTOTYPE
0039 #ifdef HAVE_CONFIG_H
0040 #include <config.h>
0041 #endif
0042 #include <ctype.h>
0043
0044 #include <stdio.h>
0045 #include <stdlib.h>
0046 #include <stdarg.h>
0047 #include <string.h>
0048 #include <signal.h>
0049 #include <time.h>
0050
0051
0052 static const char *abb_weekdays[] = {
0053 "Sun",
0054 "Mon",
0055 "Tue",
0056 "Wed",
0057 "Thu",
0058 "Fri",
0059 "Sat",
0060 NULL
0061 };
0062
0063 static const char *full_weekdays[] = {
0064 "Sunday",
0065 "Monday",
0066 "Tuesday",
0067 "Wednesday",
0068 "Thursday",
0069 "Friday",
0070 "Saturday",
0071 NULL
0072 };
0073
0074 static const char *abb_month[] = {
0075 "Jan",
0076 "Feb",
0077 "Mar",
0078 "Apr",
0079 "May",
0080 "Jun",
0081 "Jul",
0082 "Aug",
0083 "Sep",
0084 "Oct",
0085 "Nov",
0086 "Dec",
0087 NULL
0088 };
0089
0090 static const char *full_month[] = {
0091 "January",
0092 "February",
0093 "Mars",
0094 "April",
0095 "May",
0096 "June",
0097 "July",
0098 "August",
0099 "September",
0100 "October",
0101 "November",
0102 "December",
0103 NULL,
0104 };
0105
0106 static const char *ampm[] = {
0107 "am",
0108 "pm",
0109 NULL
0110 };
0111
0112
0113
0114
0115
0116
0117 static int
0118 match_string (const char **buf, const char **strs)
0119 {
0120 int i = 0;
0121
0122 for (i = 0; strs[i] != NULL; ++i) {
0123 int len = strlen (strs[i]);
0124
0125 if (strncasecmp (*buf, strs[i], len) == 0) {
0126 *buf += len;
0127 return i;
0128 }
0129 }
0130 return -1;
0131 }
0132
0133
0134
0135
0136 const int tm_year_base = 1900;
0137
0138
0139
0140
0141
0142 static int
0143 is_leap_year (int year)
0144 {
0145 return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);
0146 }
0147
0148
0149
0150
0151
0152 static int
0153 first_day (int year)
0154 {
0155 int ret = 4;
0156
0157 for (; year > 1970; --year)
0158 ret = (ret + 365 + is_leap_year (year) ? 1 : 0) % 7;
0159 return ret;
0160 }
0161
0162
0163
0164
0165
0166 static void
0167 set_week_number_sun (struct tm *timeptr, int wnum)
0168 {
0169 int fday = first_day (timeptr->tm_year + tm_year_base);
0170
0171 timeptr->tm_yday = wnum * 7 + timeptr->tm_wday - fday;
0172 if (timeptr->tm_yday < 0) {
0173 timeptr->tm_wday = fday;
0174 timeptr->tm_yday = 0;
0175 }
0176 }
0177
0178
0179
0180
0181
0182 static void
0183 set_week_number_mon (struct tm *timeptr, int wnum)
0184 {
0185 int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7;
0186
0187 timeptr->tm_yday = wnum * 7 + (timeptr->tm_wday + 6) % 7 - fday;
0188 if (timeptr->tm_yday < 0) {
0189 timeptr->tm_wday = (fday + 1) % 7;
0190 timeptr->tm_yday = 0;
0191 }
0192 }
0193
0194
0195
0196
0197
0198 static void
0199 set_week_number_mon4 (struct tm *timeptr, int wnum)
0200 {
0201 int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7;
0202 int offset = 0;
0203
0204 if (fday < 4)
0205 offset += 7;
0206
0207 timeptr->tm_yday = offset + (wnum - 1) * 7 + timeptr->tm_wday - fday;
0208 if (timeptr->tm_yday < 0) {
0209 timeptr->tm_wday = fday;
0210 timeptr->tm_yday = 0;
0211 }
0212 }
0213
0214
0215
0216
0217
0218 char *
0219 strptime (const char *buf, const char *format, struct tm *timeptr)
0220 {
0221 char c;
0222
0223 for (; (c = *format) != '\0'; ++format) {
0224 char *s;
0225 int ret;
0226
0227 if (isspace (c)) {
0228 while (isspace (*buf))
0229 ++buf;
0230 } else if (c == '%' && format[1] != '\0') {
0231 c = *++format;
0232 if (c == 'E' || c == 'O')
0233 c = *++format;
0234 switch (c) {
0235 case 'A' :
0236 ret = match_string (&buf, full_weekdays);
0237 if (ret < 0)
0238 return NULL;
0239 timeptr->tm_wday = ret;
0240 break;
0241 case 'a' :
0242 ret = match_string (&buf, abb_weekdays);
0243 if (ret < 0)
0244 return NULL;
0245 timeptr->tm_wday = ret;
0246 break;
0247 case 'B' :
0248 ret = match_string (&buf, full_month);
0249 if (ret < 0)
0250 return NULL;
0251 timeptr->tm_mon = ret;
0252 break;
0253 case 'b' :
0254 case 'h' :
0255 ret = match_string (&buf, abb_month);
0256 if (ret < 0)
0257 return NULL;
0258 timeptr->tm_mon = ret;
0259 break;
0260 case 'C' :
0261 ret = strtol (buf, &s, 10);
0262 if (s == buf)
0263 return NULL;
0264 timeptr->tm_year = (ret * 100) - tm_year_base;
0265 buf = s;
0266 break;
0267 case 'c' :
0268 abort ();
0269 case 'D' :
0270 s = strptime (buf, "%m/%d/%y", timeptr);
0271 if (s == NULL)
0272 return NULL;
0273 buf = s;
0274 break;
0275 case 'd' :
0276 case 'e' :
0277 ret = strtol (buf, &s, 10);
0278 if (s == buf)
0279 return NULL;
0280 timeptr->tm_mday = ret;
0281 buf = s;
0282 break;
0283 case 'H' :
0284 case 'k' :
0285 ret = strtol (buf, &s, 10);
0286 if (s == buf)
0287 return NULL;
0288 timeptr->tm_hour = ret;
0289 buf = s;
0290 break;
0291 case 'I' :
0292 case 'l' :
0293 ret = strtol (buf, &s, 10);
0294 if (s == buf)
0295 return NULL;
0296 if (ret == 12)
0297 timeptr->tm_hour = 0;
0298 else
0299 timeptr->tm_hour = ret;
0300 buf = s;
0301 break;
0302 case 'j' :
0303 ret = strtol (buf, &s, 10);
0304 if (s == buf)
0305 return NULL;
0306 timeptr->tm_yday = ret - 1;
0307 buf = s;
0308 break;
0309 case 'm' :
0310 ret = strtol (buf, &s, 10);
0311 if (s == buf)
0312 return NULL;
0313 timeptr->tm_mon = ret - 1;
0314 buf = s;
0315 break;
0316 case 'M' :
0317 ret = strtol (buf, &s, 10);
0318 if (s == buf)
0319 return NULL;
0320 timeptr->tm_min = ret;
0321 buf = s;
0322 break;
0323 case 'n' :
0324 if (*buf == '\n')
0325 ++buf;
0326 else
0327 return NULL;
0328 break;
0329 case 'p' :
0330 ret = match_string (&buf, ampm);
0331 if (ret < 0)
0332 return NULL;
0333 if (timeptr->tm_hour == 0) {
0334 if (ret == 1)
0335 timeptr->tm_hour = 12;
0336 } else
0337 timeptr->tm_hour += 12;
0338 break;
0339 case 'r' :
0340 s = strptime (buf, "%I:%M:%S %p", timeptr);
0341 if (s == NULL)
0342 return NULL;
0343 buf = s;
0344 break;
0345 case 'R' :
0346 s = strptime (buf, "%H:%M", timeptr);
0347 if (s == NULL)
0348 return NULL;
0349 buf = s;
0350 break;
0351 case 'S' :
0352 ret = strtol (buf, &s, 10);
0353 if (s == buf)
0354 return NULL;
0355 timeptr->tm_sec = ret;
0356 buf = s;
0357 break;
0358 case 't' :
0359 if (*buf == '\t')
0360 ++buf;
0361 else
0362 return NULL;
0363 break;
0364 case 'T' :
0365 case 'X' :
0366 s = strptime (buf, "%H:%M:%S", timeptr);
0367 if (s == NULL)
0368 return NULL;
0369 buf = s;
0370 break;
0371 case 'u' :
0372 ret = strtol (buf, &s, 10);
0373 if (s == buf)
0374 return NULL;
0375 timeptr->tm_wday = ret - 1;
0376 buf = s;
0377 break;
0378 case 'w' :
0379 ret = strtol (buf, &s, 10);
0380 if (s == buf)
0381 return NULL;
0382 timeptr->tm_wday = ret;
0383 buf = s;
0384 break;
0385 case 'U' :
0386 ret = strtol (buf, &s, 10);
0387 if (s == buf)
0388 return NULL;
0389 set_week_number_sun (timeptr, ret);
0390 buf = s;
0391 break;
0392 case 'V' :
0393 ret = strtol (buf, &s, 10);
0394 if (s == buf)
0395 return NULL;
0396 set_week_number_mon4 (timeptr, ret);
0397 buf = s;
0398 break;
0399 case 'W' :
0400 ret = strtol (buf, &s, 10);
0401 if (s == buf)
0402 return NULL;
0403 set_week_number_mon (timeptr, ret);
0404 buf = s;
0405 break;
0406 case 'x' :
0407 s = strptime (buf, "%Y:%m:%d", timeptr);
0408 if (s == NULL)
0409 return NULL;
0410 buf = s;
0411 break;
0412 case 'y' :
0413 ret = strtol (buf, &s, 10);
0414 if (s == buf)
0415 return NULL;
0416 if (ret < 70)
0417 timeptr->tm_year = 100 + ret;
0418 else
0419 timeptr->tm_year = ret;
0420 buf = s;
0421 break;
0422 case 'Y' :
0423 ret = strtol (buf, &s, 10);
0424 if (s == buf)
0425 return NULL;
0426 timeptr->tm_year = ret - tm_year_base;
0427 buf = s;
0428 break;
0429 case 'Z' :
0430 abort ();
0431 case '\0' :
0432 --format;
0433
0434 case '%' :
0435 if (*buf == '%')
0436 ++buf;
0437 else
0438 return NULL;
0439 break;
0440 default :
0441 if (*buf == '%' || *++buf == c)
0442 ++buf;
0443 else
0444 return NULL;
0445 break;
0446 }
0447 } else {
0448 if (*buf == c)
0449 ++buf;
0450 else
0451 return NULL;
0452 }
0453 }
0454 return (char *)buf;
0455 }
0456
0457 #endif
0458 }
0459
0460 #endif