📄 piece.xs
字号:
buf = _strptime(buf, Locale->x_fmt, tm); if (buf == 0) return 0; break; case 'j': if (!isdigit((unsigned char)*buf)) return 0; len = 3; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i < 1 || i > 366) return 0; tm->tm_yday = i - 1; break; case 'M': case 'S': if (*buf == 0 || isspace((unsigned char)*buf)) break; if (!isdigit((unsigned char)*buf)) return 0; len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (c == 'M') { if (i > 59) return 0; tm->tm_min = i; } else { if (i > 60) return 0; tm->tm_sec = i; } if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'H': case 'I': case 'k': case 'l': /* * Of these, %l is the only specifier explicitly * documented as not being zero-padded. However, * there is no harm in allowing zero-padding. * * XXX The %l specifier may gobble one too many * digits if used incorrectly. */ if (!isdigit((unsigned char)*buf)) return 0; len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (c == 'H' || c == 'k') { if (i > 23) return 0; } else if (i > 12) return 0; tm->tm_hour = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'p': /* * XXX This is bogus if parsed before hour-related * specifiers. */ len = strlen(Locale->am); if (strncasecmp(buf, Locale->am, len) == 0) { if (tm->tm_hour > 12) return 0; if (tm->tm_hour == 12) tm->tm_hour = 0; buf += len; break; } len = strlen(Locale->pm); if (strncasecmp(buf, Locale->pm, len) == 0) { if (tm->tm_hour > 12) return 0; if (tm->tm_hour != 12) tm->tm_hour += 12; buf += len; break; } return 0; case 'A': case 'a': for (i = 0; i < asizeof(Locale->weekday); i++) { if (c == 'A') { len = strlen(Locale->weekday[i]); if (strncasecmp(buf, Locale->weekday[i], len) == 0) break; } else { len = strlen(Locale->wday[i]); if (strncasecmp(buf, Locale->wday[i], len) == 0) break; } } if (i == asizeof(Locale->weekday)) return 0; tm->tm_wday = i; buf += len; break; case 'U': case 'W': /* * XXX This is bogus, as we can not assume any valid * information present in the tm structure at this * point to calculate a real value, so just check the * range for now. */ if (!isdigit((unsigned char)*buf)) return 0; len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i > 53) return 0; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'w': if (!isdigit((unsigned char)*buf)) return 0; i = *buf - '0'; if (i > 6) return 0; tm->tm_wday = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'd': case 'e': /* * The %e specifier is explicitly documented as not * being zero-padded but there is no harm in allowing * such padding. * * XXX The %e specifier may gobble one too many * digits if used incorrectly. */ if (!isdigit((unsigned char)*buf)) return 0; len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i > 31) return 0; tm->tm_mday = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'B': case 'b': case 'h': for (i = 0; i < asizeof(Locale->month); i++) { if (Oalternative) { if (c == 'B') { len = strlen(Locale->alt_month[i]); if (strncasecmp(buf, Locale->alt_month[i], len) == 0) break; } } else { if (c == 'B') { len = strlen(Locale->month[i]); if (strncasecmp(buf, Locale->month[i], len) == 0) break; } else { len = strlen(Locale->mon[i]); if (strncasecmp(buf, Locale->mon[i], len) == 0) break; } } } if (i == asizeof(Locale->month)) return 0; tm->tm_mon = i; buf += len; break; case 'm': if (!isdigit((unsigned char)*buf)) return 0; len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i < 1 || i > 12) return 0; tm->tm_mon = i - 1; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'Y': case 'y': if (*buf == 0 || isspace((unsigned char)*buf)) break; if (!isdigit((unsigned char)*buf)) return 0; len = (c == 'Y') ? 4 : 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (c == 'Y') i -= 1900; if (c == 'y' && i < 69) i += 100; if (i < 0) return 0; tm->tm_year = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'Z': { const char *cp; char *zonestr; for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/} if (cp - buf) { zonestr = (char *)alloca(cp - buf + 1); strncpy(zonestr, buf, cp - buf); zonestr[cp - buf] = '\0'; tzset(); if (0 == strcmp(zonestr, "GMT")) { got_GMT = 1; } else { return 0; } buf += cp - buf; } } break; } } return (char *)buf;}char *strptime(const char *buf, const char *fmt, struct tm *tm){ char *ret;#ifdef _THREAD_SAFEpthread_mutex_lock(&gotgmt_mutex);#endif got_GMT = 0; ret = _strptime(buf, fmt, tm);#ifdef _THREAD_SAFE pthread_mutex_unlock(&gotgmt_mutex);#endif return ret;}#endif /* Mac OS X */MODULE = Time::Piece PACKAGE = Time::PiecePROTOTYPES: ENABLEvoid_strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1) char * fmt int sec int min int hour int mday int mon int year int wday int yday int isdst CODE: { char tmpbuf[128]; struct tm mytm; int len; memset(&mytm, 0, sizeof(mytm)); my_init_tm(&mytm); /* XXX workaround - see my_init_tm() above */ mytm.tm_sec = sec; mytm.tm_min = min; mytm.tm_hour = hour; mytm.tm_mday = mday; mytm.tm_mon = mon; mytm.tm_year = year; mytm.tm_wday = wday; mytm.tm_yday = yday; mytm.tm_isdst = isdst; my_mini_mktime(&mytm); len = strftime(tmpbuf, sizeof tmpbuf, fmt, &mytm); /* ** The following is needed to handle to the situation where ** tmpbuf overflows. Basically we want to allocate a buffer ** and try repeatedly. The reason why it is so complicated ** is that getting a return value of 0 from strftime can indicate ** one of the following: ** 1. buffer overflowed, ** 2. illegal conversion specifier, or ** 3. the format string specifies nothing to be returned(not ** an error). This could be because format is an empty string ** or it specifies %p that yields an empty string in some locale. ** If there is a better way to make it portable, go ahead by ** all means. */ if ((len > 0 && len < sizeof(tmpbuf)) || (len == 0 && *fmt == '\0')) ST(0) = sv_2mortal(newSVpv(tmpbuf, len)); else { /* Possibly buf overflowed - try again with a bigger buf */ int fmtlen = strlen(fmt); int bufsize = fmtlen + sizeof(tmpbuf); char* buf; int buflen; New(0, buf, bufsize, char); while (buf) { buflen = strftime(buf, bufsize, fmt, &mytm); if (buflen > 0 && buflen < bufsize) break; /* heuristic to prevent out-of-memory errors */ if (bufsize > 100*fmtlen) { Safefree(buf); buf = NULL; break; } bufsize *= 2; Renew(buf, bufsize, char); } if (buf) { ST(0) = sv_2mortal(newSVpv(buf, buflen)); Safefree(buf); } else ST(0) = sv_2mortal(newSVpv(tmpbuf, len)); } }void_tzset() PPCODE: tzset();void_strptime ( string, format ) char * string char * format PREINIT: struct tm mytm; time_t t; char * remainder; PPCODE: t = 0; mytm = *gmtime(&t); remainder = (char *)strptime(string, format, &mytm); if (remainder == NULL) { croak("Error parsing time"); } if (*remainder != '\0') { warn("garbage at end of string in strptime: %s", remainder); } my_mini_mktime(&mytm); /* warn("tm: %d-%d-%d %d:%d:%d\n", mytm.tm_year, mytm.tm_mon, mytm.tm_mday, mytm.tm_hour, mytm.tm_min, mytm.tm_sec); */ EXTEND(SP, 11); PUSHs(sv_2mortal(newSViv(mytm.tm_sec))); PUSHs(sv_2mortal(newSViv(mytm.tm_min))); PUSHs(sv_2mortal(newSViv(mytm.tm_hour))); PUSHs(sv_2mortal(newSViv(mytm.tm_mday))); PUSHs(sv_2mortal(newSViv(mytm.tm_mon))); PUSHs(sv_2mortal(newSViv(mytm.tm_year))); PUSHs(sv_2mortal(newSViv(mytm.tm_wday))); PUSHs(sv_2mortal(newSViv(mytm.tm_yday))); /* isdst */ PUSHs(sv_2mortal(newSViv(0))); /* epoch */ PUSHs(sv_2mortal(newSViv(0))); /* islocal */ PUSHs(sv_2mortal(newSViv(0)));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -