String LocaleWin::formatDate(const Vector<DateFormatToken>& tokens, int baseYear, int year, int month, int day) { ensureShortMonthLabels(); ensureMonthLabels(); StringBuilder buffer; for (unsigned i = 0; i < tokens.size(); ++i) { switch (tokens[i].type) { case DateFormatToken::Literal: buffer.append(tokens[i].data); break; case DateFormatToken::Day1: appendNumber(day, buffer); break; case DateFormatToken::Day2: appendTwoDigitsNumber(day, buffer); break; case DateFormatToken::Month1: appendNumber(month + 1, buffer); break; case DateFormatToken::Month2: appendTwoDigitsNumber(month + 1, buffer); break; case DateFormatToken::Month3: if (0 <= month && month < static_cast<int>(m_shortMonthLabels.size())) buffer.append(m_shortMonthLabels[month]); else appendNumber(month + 1, buffer); break; case DateFormatToken::Month4: if (0 <= month && month < static_cast<int>(m_monthLabels.size())) buffer.append(m_monthLabels[month]); else appendNumber(month + 1, buffer); break; case DateFormatToken::Year1: { if (baseYear - 4 <= year && year <= baseYear + 5) appendNumber(year % 10, buffer); else appendFourDigitsNumber(year, buffer); break; } case DateFormatToken::Year2: { if (baseYear - 49 <= year && year <= baseYear + 50) appendTwoDigitsNumber(year % 100, buffer); else appendFourDigitsNumber(year, buffer); break; } case DateFormatToken::Year4: appendFourDigitsNumber(year, buffer); break; } } return buffer.toString(); }
const Vector<String>& LocaleWin::shortMonthLabels() { ensureShortMonthLabels(); return m_shortMonthLabels; }
double LocaleWin::parseDate(const Vector<DateFormatToken>& tokens, int baseYear, const String& input) { ensureShortMonthLabels(); ensureMonthLabels(); const double NaN = numeric_limits<double>::quiet_NaN(); unsigned inputIndex = 0; int day = -1, month = -1, year = -1; for (unsigned i = 0; i < tokens.size(); ++i) { switch (tokens[i].type) { case DateFormatToken::Literal: { String data = tokens[i].data; unsigned literalLength = data.length(); if (input.substring(inputIndex, literalLength) == data) inputIndex += literalLength; // Go ahead even if the input doesn't have this string. break; } case DateFormatToken::Day1: case DateFormatToken::Day2: day = parseNumber(input, inputIndex); if (day < 1 || day > 31) return NaN; break; case DateFormatToken::Month1: case DateFormatToken::Month2: case DateFormatToken::Month3: case DateFormatToken::Month4: month = parseNumberOrMonth(input, inputIndex); if (month < 0 || month > 11) return NaN; break; case DateFormatToken::Year1: { unsigned oldIndex = inputIndex; year = parseNumber(input, inputIndex); if (year <= 0) return NaN; if (inputIndex - oldIndex == 1) { int shortYear = baseYear % 10; int decade = baseYear - shortYear; if (shortYear >= 5) year += shortYear - 4 <= year ? decade : decade + 10; else year += shortYear + 5 >= year ? decade : decade - 10; } break; } case DateFormatToken::Year2: { unsigned oldIndex = inputIndex; year = parseNumber(input, inputIndex); if (year <= 0) return NaN; if (inputIndex - oldIndex == 2) { int shortYear = baseYear % 100; int century = baseYear - shortYear; if (shortYear >= 50) year += shortYear - 49 <= year ? century : century + 100; else year += shortYear + 50 >= year ? century : century - 100; } break; } case DateFormatToken::Year4: year = parseNumber(input, inputIndex); if (year <= 0) return NaN; break; } } if (year <= 0 || month < 0 || day <= 0) return NaN; return dateToDaysFrom1970(year, month, day) * msPerDay; }