5#include "../include/macros.h"
6#include "../include/win_strptime.h"
13static inline bool is_leap_year(
int year) {
15 int actual_year = year + 1900;
16 return (actual_year % 4 == 0 && actual_year % 100 != 0) || (actual_year % 400 == 0);
22static inline int days_in_month(
int month,
int year) {
23 static const int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
24 if (month < 0 || month > 11) {
27 if (month == 1 && is_leap_year(year)) {
36static inline bool is_valid_date(
int day,
int month,
int year) {
37 if (month < 0 || month > 11) {
43 return day <= days_in_month(month, year);
57char* strptime(
const char* buf,
const char* fmt,
struct tm* tm) {
58 if (buf == NULL || fmt == NULL || tm == NULL) {
65 bool has_ampm =
false;
67 bool need_date_validation =
false;
72 if (tm->tm_wday == 0 && tm->tm_yday == 0 && tm->tm_isdst == 0) {
78 if (isspace((
unsigned char)*f)) {
79 while (isspace((
unsigned char)*f)) f++;
80 while (isspace((
unsigned char)*s)) s++;
102 bool has_modifier =
false;
103 if (*f ==
'E' || *f ==
'O') {
113 if (!isdigit((
unsigned char)s[0]) || !isdigit((
unsigned char)s[1]) || !isdigit((
unsigned char)s[2]) ||
114 !isdigit((
unsigned char)s[3])) {
117 int year = (s[0] -
'0') * 1000 + (s[1] -
'0') * 100 + (s[2] -
'0') * 10 + (s[3] -
'0');
118 tm->tm_year = year - 1900;
124 if (!isdigit((
unsigned char)s[0]) || !isdigit((
unsigned char)s[1])) {
127 int year = (s[0] -
'0') * 10 + (s[1] -
'0');
130 tm->tm_year = century * 100 + year - 1900;
132 tm->tm_year = (year >= 69) ? year : (year + 100);
139 if (!isdigit((
unsigned char)s[0]) || !isdigit((
unsigned char)s[1])) {
142 century = (s[0] -
'0') * 10 + (s[1] -
'0');
148 if (!isdigit((
unsigned char)s[0]) || !isdigit((
unsigned char)s[1])) {
151 int month = (s[0] -
'0') * 10 + (s[1] -
'0');
152 if (month < 1 || month > 12) {
155 tm->tm_mon = month - 1;
156 need_date_validation =
true;
162 if (!isdigit((
unsigned char)s[0]) || !isdigit((
unsigned char)s[1])) {
165 int day = (s[0] -
'0') * 10 + (s[1] -
'0');
166 if (day < 1 || day > 31) {
170 need_date_validation =
true;
177 if (*s ==
' ' || *s ==
'0') {
180 if (!isdigit((
unsigned char)s[0])) {
183 int day = (s[0] -
'0');
185 if (isdigit((
unsigned char)s[0])) {
186 day = day * 10 + (s[0] -
'0');
189 if (day < 1 || day > 31) {
193 need_date_validation =
true;
198 if (!isdigit((
unsigned char)s[0]) || !isdigit((
unsigned char)s[1])) {
201 int hour = (s[0] -
'0') * 10 + (s[1] -
'0');
214 if (!isdigit((
unsigned char)s[0])) {
217 int hour = (s[0] -
'0');
219 if (isdigit((
unsigned char)s[0])) {
220 hour = hour * 10 + (s[0] -
'0');
231 if (!isdigit((
unsigned char)s[0]) || !isdigit((
unsigned char)s[1])) {
234 int hour = (s[0] -
'0') * 10 + (s[1] -
'0');
235 if (hour < 1 || hour > 12) {
247 if (!isdigit((
unsigned char)s[0])) {
250 int hour = (s[0] -
'0');
252 if (isdigit((
unsigned char)s[0])) {
253 hour = hour * 10 + (s[0] -
'0');
256 if (hour < 1 || hour > 12) {
264 if (!isdigit((
unsigned char)s[0]) || !isdigit((
unsigned char)s[1])) {
267 int min = (s[0] -
'0') * 10 + (s[1] -
'0');
277 if (!isdigit((
unsigned char)s[0]) || !isdigit((
unsigned char)s[1])) {
280 int sec = (s[0] -
'0') * 10 + (s[1] -
'0');
290 if ((s[0] ==
'A' || s[0] ==
'a') && (s[1] ==
'M' || s[1] ==
'm')) {
294 }
else if ((s[0] ==
'P' || s[0] ==
'p') && (s[1] ==
'M' || s[1] ==
'm')) {
305 char* result = strptime(s,
"%I:%M:%S %p", tm);
306 if (result == NULL) {
315 char* result = strptime(s,
"%H:%M", tm);
316 if (result == NULL) {
324 char* result = strptime(s,
"%H:%M:%S", tm);
325 if (result == NULL) {
333 char* result = strptime(s,
"%m/%d/%y", tm);
334 if (result == NULL) {
342 char* result = strptime(s,
"%Y-%m-%d", tm);
343 if (result == NULL) {
353 static const char* months[] = {
"january",
"february",
"march",
"april",
"may",
"june",
354 "july",
"august",
"september",
"october",
"november",
"december"};
355 static const char* abbr_months[] = {
"jan",
"feb",
"mar",
"apr",
"may",
"jun",
356 "jul",
"aug",
"sep",
"oct",
"nov",
"dec"};
360 for (
int i = 0; i < 12; i++) {
361 const char* full = months[i];
362 const char* abbr = abbr_months[i];
363 size_t full_len = strlen(full);
368 if (_strnicmp(s, full, full_len) == 0) {
375 if (_strnicmp(s, abbr, abbr_len) == 0) {
386 need_date_validation =
true;
392 static const char* weekdays[] = {
"sunday",
"monday",
"tuesday",
"wednesday",
393 "thursday",
"friday",
"saturday"};
394 static const char* abbr_weekdays[] = {
"sun",
"mon",
"tue",
"wed",
"thu",
"fri",
"sat"};
397 for (
int i = 0; i < 7; i++) {
398 const char* full = weekdays[i];
399 const char* abbr = abbr_weekdays[i];
400 size_t full_len = strlen(full);
404 if (_strnicmp(s, full, full_len) == 0) {
411 if (_strnicmp(s, abbr, abbr_len) == 0) {
426 if (!isdigit((
unsigned char)s[0]) || !isdigit((
unsigned char)s[1]) || !isdigit((
unsigned char)s[2])) {
429 int yday = (s[0] -
'0') * 100 + (s[1] -
'0') * 10 + (s[2] -
'0');
430 if (yday < 1 || yday > 366) {
433 tm->tm_yday = yday - 1;
439 if (!isdigit((
unsigned char)s[0])) {
442 int wday = s[0] -
'0';
443 if (wday < 1 || wday > 7) {
446 tm->tm_wday = (wday == 7) ? 0 : wday;
452 if (!isdigit((
unsigned char)s[0])) {
455 int wday = s[0] -
'0';
467 if (*s ==
'+' || *s ==
'-') {
470 if (isdigit((
unsigned char)s[0]) && isdigit((
unsigned char)s[1])) {
480 if (isdigit((
unsigned char)s[0]) && isdigit((
unsigned char)s[1])) {
485 }
else if (*s ==
'Z' || *s ==
'z') {
495 while (*s !=
'\0' && !isspace((
unsigned char)*s) && *s !=
'+' && *s !=
'-' &&
496 isalpha((
unsigned char)*s)) {
508 if (!isspace((
unsigned char)*s)) {
511 while (isspace((
unsigned char)*s)) {
535 if (is_pm && tm->tm_hour < 12) {
537 }
else if (!is_pm && tm->tm_hour == 12) {
543 if (need_date_validation && !is_valid_date(tm->tm_mday, tm->tm_mon, tm->tm_year)) {
548 if (tm->tm_isdst == 0) {