/* *"Complex"conversionrules,implementedthroughrecursion.
*/ case'c': /* Date and time, using the locale's format. */
_LEGAL_ALT(_ALT_E); if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, 0))) return (NULL); break;
case'D': /* The date as "%m/%d/%y". */
_LEGAL_ALT(0); if (!(bp = _strptime(bp, "%m/%d/%y", tm, 0))) return (NULL); break;
case'F': /* The date as "%Y-%m-%d". */
_LEGAL_ALT(0); if (!(bp = _strptime(bp, "%Y-%m-%d", tm, 0))) return (NULL); continue;
case'R': /* The time as "%H:%M". */
_LEGAL_ALT(0); if (!(bp = _strptime(bp, "%H:%M", tm, 0))) return (NULL); break;
case'r': /* The time as "%I:%M:%S %p". */
_LEGAL_ALT(0); if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, 0))) return (NULL); break;
case'T': /* The time as "%H:%M:%S". */
_LEGAL_ALT(0); if (!(bp = _strptime(bp, "%H:%M:%S", tm, 0))) return (NULL); break;
case'v': /* The date as "%e-%b-%Y". */
_LEGAL_ALT(0); if (!(bp = _strptime(bp, "%e-%b-%Y", tm, 0))) return (NULL); break;
case'X': /* The time, using the locale's format. */
_LEGAL_ALT(_ALT_E); if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, 0))) return (NULL); break;
case'x': /* The date, using the locale's format. */
_LEGAL_ALT(_ALT_E); if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, 0))) return (NULL); break;
/* *"Elementary"conversionrules.
*/ case'A': /* The day of week, using the locale's form. */ case'a':
_LEGAL_ALT(0); for (i = 0; i < 7; i++) { /* Full name. */
len = strlen(_ctloc(day[i])); if (strncasecmp(_ctloc(day[i]), bp, len) == 0) break;
/* Abbreviated name. */
len = strlen(_ctloc(abday[i])); if (strncasecmp(_ctloc(abday[i]), bp, len) == 0) break;
}
/* Nothing matched. */ if (i == 7) return (NULL);
tm->tm_wday = i;
bp += len;
fields |= FIELD_TM_WDAY; break;
case'B': /* The month, using the locale's form. */ case'b': case'h':
_LEGAL_ALT(0); for (i = 0; i < 12; i++) { /* Full name. */
len = strlen(_ctloc(mon[i])); if (strncasecmp(_ctloc(mon[i]), bp, len) == 0) break;
/* Abbreviated name. */
len = strlen(_ctloc(abmon[i])); if (strncasecmp(_ctloc(abmon[i]), bp, len) == 0) break;
}
/* Nothing matched. */ if (i == 12) return (NULL);
tm->tm_mon = i;
bp += len;
fields |= FIELD_TM_MON; break;
case'C': /* The century number. */
_LEGAL_ALT(_ALT_E); if (!(_conv_num(&bp, &i, 0, 99))) return (NULL);
century = i * 100; break;
case'e': /* The day of month. */ if (isspace(*bp))
bp++; /* FALLTHROUGH */ case'd':
_LEGAL_ALT(_ALT_O); if (!(_conv_num(&bp, &tm->tm_mday, 1, 31))) return (NULL);
fields |= FIELD_TM_MDAY; break;
case'j': /* The day of year. */
_LEGAL_ALT(0); if (!(_conv_num(&bp, &tm->tm_yday, 1, 366))) return (NULL);
tm->tm_yday--;
fields |= FIELD_TM_YDAY; break;
case'M': /* The minute. */
_LEGAL_ALT(_ALT_O); if (!(_conv_num(&bp, &tm->tm_min, 0, 59))) return (NULL); break;
case'm': /* The month. */
_LEGAL_ALT(_ALT_O); if (!(_conv_num(&bp, &tm->tm_mon, 1, 12))) return (NULL);
tm->tm_mon--;
fields |= FIELD_TM_MON; break;
case'P': /* Android addition for strftime() compat; glibc does this too. */ case'p': /* The locale's equivalent of AM/PM. */
_LEGAL_ALT(0); /* AM? */
len = strlen(_ctloc(am_pm[0])); if (strncasecmp(_ctloc(am_pm[0]), bp, len) == 0) { if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */ return (NULL); elseif (tm->tm_hour == 12)
tm->tm_hour = 0;
bp += len; break;
} /* PM? */
len = strlen(_ctloc(am_pm[1])); if (strncasecmp(_ctloc(am_pm[1]), bp, len) == 0) { if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */ return (NULL); elseif (tm->tm_hour < 12)
tm->tm_hour += 12;
bp += len; break;
}
/* Nothing matched. */ return (NULL);
case'S': /* The seconds. */
_LEGAL_ALT(_ALT_O); if (!(_conv_num(&bp, &tm->tm_sec, 0, 60))) return (NULL); break; case's': /* Seconds since epoch. */ if (!(epoch_to_tm(&bp, tm))) return (NULL);
fields = 0xffff; /* everything */ break; case'U': /* The week of year, beginning on sunday. */ case'W': /* The week of year, beginning on monday. */
_LEGAL_ALT(_ALT_O); /* *XXXThisisbogus,aswecannotassumeanyvalid *informationpresentinthetmstructureatthis *pointtocalculatearealvalue,sojustcheckthe *rangefornow.
*/ if (!(_conv_num(&bp, &i, 0, 53))) return (NULL); break;
case'w': /* The day of week, beginning on sunday. */
_LEGAL_ALT(_ALT_O); if (!(_conv_num(&bp, &tm->tm_wday, 0, 6))) return (NULL);
fields |= FIELD_TM_WDAY; break;
case'u': /* The day of week, monday = 1. */
_LEGAL_ALT(_ALT_O); if (!(_conv_num(&bp, &i, 1, 7))) return (NULL);
tm->tm_wday = i % 7;
fields |= FIELD_TM_WDAY; continue;
case'g': /* The year corresponding to the ISO week *numberbutwithoutthecentury.
*/ if (!(_conv_num(&bp, &i, 0, 99))) return (NULL); continue;
case'G': /* The year corresponding to the ISO week *numberwithcentury.
*/ do
bp++; while (isdigit(*bp)); continue;
case'V': /* The ISO 8601:1988 week number as decimal */ if (!(_conv_num(&bp, &i, 0, 53))) return (NULL); continue;
case'Y': /* The year. */
_LEGAL_ALT(_ALT_E); if (!(_conv_num(&bp, &i, 0, 9999))) return (NULL);
/* Compute some missing values when possible. */ if (fields & FIELD_TM_YEAR) { constint year = tm->tm_year + TM_YEAR_BASE; constint *mon_lens = mon_lengths[isleap(year)]; if (!(fields & FIELD_TM_YDAY) &&
(fields & FIELD_TM_MON) && (fields & FIELD_TM_MDAY)) {
tm->tm_yday = tm->tm_mday - 1; for (i = 0; i < tm->tm_mon; i++)
tm->tm_yday += mon_lens[i];
fields |= FIELD_TM_YDAY;
} if (fields & FIELD_TM_YDAY) { int days = tm->tm_yday; if (!(fields & FIELD_TM_WDAY)) {
tm->tm_wday = EPOCH_WDAY +
((year - EPOCH_YEAR) % DAYSPERWEEK) *
(DAYSPERNYEAR % DAYSPERWEEK) +
leaps_thru_end_of(year - 1) -
leaps_thru_end_of(EPOCH_YEAR - 1) +
tm->tm_yday;
tm->tm_wday %= DAYSPERWEEK; if (tm->tm_wday < 0)
tm->tm_wday += DAYSPERWEEK;
} if (!(fields & FIELD_TM_MON)) {
tm->tm_mon = 0; while (tm->tm_mon < MONSPERYEAR && days >= mon_lens[tm->tm_mon])
days -= mon_lens[tm->tm_mon++];
} if (!(fields & FIELD_TM_MDAY))
tm->tm_mday = days + 1;
}
}
return ((char *)bp);
}
staticint
_conv_num(constunsignedchar **buf, int *dest, int llim, int ulim)
{ int result = 0; int rulim = ulim;
if (**buf < '0' || **buf > '9') return (0);
/* we use rulim to break out of the loop when we run out of digits */ do {
result *= 10;
result += *(*buf)++ - '0';
rulim /= 10;
} while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
if (result < llim || result > ulim) return (0);
*dest = result; return (1);
}
staticint
epoch_to_tm(constunsignedchar **buf, struct tm *tm)
{ int saved_errno = errno; int ret = 0;
time_t secs; char *ep;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.