📄 prtime.c
字号:
case 'o': case 'O': if (month == TT_UNKNOWN && (rest[1] == 'c' || rest[1] == 'C') && (rest[2] == 't' || rest[2] == 'T')) month = TT_OCT; break; case 'p': case 'P': if (zone == TT_UNKNOWN && (rest[1] == 'd' || rest[1] == 'D') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_PDT; else if (zone == TT_UNKNOWN && (rest[1] == 's' || rest[1] == 'S') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_PST; break; case 's': case 'S': if (dotw == TT_UNKNOWN && (rest[1] == 'a' || rest[1] == 'A') && (rest[2] == 't' || rest[2] == 'T')) dotw = TT_SAT; else if (month == TT_UNKNOWN && (rest[1] == 'e' || rest[1] == 'E') && (rest[2] == 'p' || rest[2] == 'P')) month = TT_SEP; else if (dotw == TT_UNKNOWN && (rest[1] == 'u' || rest[1] == 'U') && (rest[2] == 'n' || rest[2] == 'N')) dotw = TT_SUN; break; case 't': case 'T': if (dotw == TT_UNKNOWN && (rest[1] == 'h' || rest[1] == 'H') && (rest[2] == 'u' || rest[2] == 'U')) dotw = TT_THU; else if (dotw == TT_UNKNOWN && (rest[1] == 'u' || rest[1] == 'U') && (rest[2] == 'e' || rest[2] == 'E')) dotw = TT_TUE; break; case 'u': case 'U': if (zone == TT_UNKNOWN && (rest[1] == 't' || rest[1] == 'T') && !(rest[2] >= 'A' && rest[2] <= 'Z') && !(rest[2] >= 'a' && rest[2] <= 'z')) /* UT is the same as GMT but UTx is not. */ zone = TT_GMT; break; case 'w': case 'W': if (dotw == TT_UNKNOWN && (rest[1] == 'e' || rest[1] == 'E') && (rest[2] == 'd' || rest[2] == 'D')) dotw = TT_WED; break; case '+': case '-': { const char *end; int sign; if (zone_offset != -1) { /* already got one... */ rest++; break; } if (zone != TT_UNKNOWN && zone != TT_GMT) { /* GMT+0300 is legal, but PST+0300 is not. */ rest++; break; } sign = ((*rest == '+') ? 1 : -1); rest++; /* move over sign */ end = rest; while (*end >= '0' && *end <= '9') end++; if (rest == end) /* no digits here */ break; if ((end - rest) == 4) /* offset in HHMM */ zone_offset = (((((rest[0]-'0')*10) + (rest[1]-'0')) * 60) + (((rest[2]-'0')*10) + (rest[3]-'0'))); else if ((end - rest) == 2) /* offset in hours */ zone_offset = (((rest[0]-'0')*10) + (rest[1]-'0')) * 60; else if ((end - rest) == 1) /* offset in hours */ zone_offset = (rest[0]-'0') * 60; else /* 3 or >4 */ break; zone_offset *= sign; zone = TT_GMT; break; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int tmp_hour = -1; int tmp_min = -1; int tmp_sec = -1; const char *end = rest + 1; while (*end >= '0' && *end <= '9') end++; /* end is now the first character after a range of digits. */ if (*end == ':') { if (hour >= 0 && min >= 0) /* already got it */ break; /* We have seen "[0-9]+:", so this is probably HH:MM[:SS] */ if ((end - rest) > 2) /* it is [0-9][0-9][0-9]+: */ break; else if ((end - rest) == 2) tmp_hour = ((rest[0]-'0')*10 + (rest[1]-'0')); else tmp_hour = (rest[0]-'0'); while (*rest && *rest != ':') rest++; rest++; /* move over the colon, and parse minutes */ end = rest + 1; while (*end >= '0' && *end <= '9') end++; if (end == rest) /* no digits after first colon? */ break; else if ((end - rest) > 2) /* it is [0-9][0-9][0-9]+: */ break; else if ((end - rest) == 2) tmp_min = ((rest[0]-'0')*10 + (rest[1]-'0')); else tmp_min = (rest[0]-'0'); /* now go for seconds */ rest = end; if (*rest == ':') rest++; end = rest; while (*end >= '0' && *end <= '9') end++; if (end == rest) /* no digits after second colon - that's ok. */ ; else if ((end - rest) > 2) /* it is [0-9][0-9][0-9]+: */ break; else if ((end - rest) == 2) tmp_sec = ((rest[0]-'0')*10 + (rest[1]-'0')); else tmp_sec = (rest[0]-'0'); /* If we made it here, we've parsed hour and min, and possibly sec, so it worked as a unit. */ /* skip over whitespace and see if there's an AM or PM directly following the time. */ if (tmp_hour <= 12) { const char *s = end; while (*s && (*s == ' ' || *s == '\t')) s++; if ((s[0] == 'p' || s[0] == 'P') && (s[1] == 'm' || s[1] == 'M')) /* 10:05pm == 22:05, and 12:05pm == 12:05 */ tmp_hour = (tmp_hour == 12 ? 12 : tmp_hour + 12); else if (tmp_hour == 12 && (s[0] == 'a' || s[0] == 'A') && (s[1] == 'm' || s[1] == 'M')) /* 12:05am == 00:05 */ tmp_hour = 0; } hour = tmp_hour; min = tmp_min; sec = tmp_sec; rest = end; break; } else if ((*end == '/' || *end == '-') && end[1] >= '0' && end[1] <= '9') { /* Perhaps this is 6/16/95, 16/6/95, 6-16-95, or 16-6-95 or even 95-06-05... #### But it doesn't handle 1995-06-22. */ int n1, n2, n3; const char *s; if (month != TT_UNKNOWN) /* if we saw a month name, this can't be. */ break; s = rest; n1 = (*s++ - '0'); /* first 1 or 2 digits */ if (*s >= '0' && *s <= '9') n1 = n1*10 + (*s++ - '0'); if (*s != '/' && *s != '-') /* slash */ break; s++; if (*s < '0' || *s > '9') /* second 1 or 2 digits */ break; n2 = (*s++ - '0'); if (*s >= '0' && *s <= '9') n2 = n2*10 + (*s++ - '0'); if (*s != '/' && *s != '-') /* slash */ break; s++; if (*s < '0' || *s > '9') /* third 1, 2, or 4 digits */ break; n3 = (*s++ - '0'); if (*s >= '0' && *s <= '9') n3 = n3*10 + (*s++ - '0'); if (*s >= '0' && *s <= '9') /* optional digits 3 and 4 */ { n3 = n3*10 + (*s++ - '0'); if (*s < '0' || *s > '9') break; n3 = n3*10 + (*s++ - '0'); } if ((*s >= '0' && *s <= '9') || /* followed by non-alphanum */ (*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z')) break; /* Ok, we parsed three 1-2 digit numbers, with / or - between them. Now decide what the hell they are (DD/MM/YY or MM/DD/YY or YY/MM/DD.) */ if (n1 > 31 || n1 == 0) /* must be YY/MM/DD */ { if (n2 > 12) break; if (n3 > 31) break; year = n1; if (year < 70) year += 2000; else if (year < 100) year += 1900; month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1); date = n3; rest = s; break; } if (n1 > 12 && n2 > 12) /* illegal */ { rest = s; break; } if (n3 < 70) n3 += 2000; else if (n3 < 100) n3 += 1900; if (n1 > 12) /* must be DD/MM/YY */ { date = n1; month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1); year = n3; } else /* assume MM/DD/YY */ { /* #### In the ambiguous case, should we consult the locale to find out the local default? */ month = (TIME_TOKEN)(n1 + ((int)TT_JAN) - 1); date = n2; year = n3; } rest = s; } else if ((*end >= 'A' && *end <= 'Z') || (*end >= 'a' && *end <= 'z')) /* Digits followed by non-punctuation - what's that? */ ; else if ((end - rest) == 4) /* four digits is a year */ year = (year < 0 ? ((rest[0]-'0')*1000L + (rest[1]-'0')*100L + (rest[2]-'0')*10L + (rest[3]-'0')) : year); else if ((end - rest) == 2) /* two digits - date or year */ { int n = ((rest[0]-'0')*10 + (rest[1]-'0')); /* If we don't have a date (day of the month) and we see a number less than 32, then assume that is the date. Otherwise, if we have a date and not a year, assume this is the year. If it is less than 70, then assume it refers to the 21st century. If it is two digits (>= 70), assume it refers to this century. Otherwise, assume it refers to an unambiguous year. The world will surely end soon. */ if (date < 0 && n < 32) date = n; else if (year < 0) { if (n < 70) year = 2000 + n; else if (n < 100) year = 1900 + n; else year = n; } /* else what the hell is this. */ } else if ((end - rest) == 1) /* one digit - date */ date = (date < 0 ? (rest[0]-'0') : date); /* else, three or more than four digits - what's that? */ break; } } /* Skip to the end of this token, whether we parsed it or not. Tokens are delimited by whitespace, or ,;-/ But explicitly not :+-. */ while (*rest && *rest != ' ' && *rest != '\t' && *rest != ',' && *rest != ';' && *rest != '-' && *rest != '+' && *rest != '/' && *rest != '(' && *rest != ')' && *rest != '[' && *rest != ']') rest++; /* skip over uninteresting chars. */ SKIP_MORE: while (*rest && (*rest == ' ' || *rest == '\t' || *rest == ',' || *rest == ';' || *rest == '/' || *rest == '(' || *rest == ')' || *rest == '[' || *rest == ']')) rest++; /* "-" is ignored at the beginning of a token if we have not yet parsed a year (e.g., the second "-" in "30-AUG-1966"), or if the character after the dash is not a digit. */ if (*rest == '-' && ((rest > string && isalpha(rest[-1]) && year < 0) || rest[1] < '0' || rest[1] > '9')) { rest++; goto SKIP_MORE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -