// This function converts Windows date/time pattern format [1][2] into LDML date
// format pattern [3].
//
// i.e.
//   We set h, H, m, s, d, dd, M, or y as is. They have same meaning in both of
//   Windows and LDML.
//   We need to convert the following patterns:
//     t -> a
//     tt -> a
//     ddd -> EEE
//     dddd -> EEEE
//     g -> G
//     gg -> ignore
//
// [1] http://msdn.microsoft.com/en-us/library/dd317787(v=vs.85).aspx
// [2] http://msdn.microsoft.com/en-us/library/dd318148(v=vs.85).aspx
// [3] LDML http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns
static String convertWindowsDateTimeFormat(const String& format)
{
    StringBuilder converted;
    StringBuilder literalBuffer;
    bool inQuote = false;
    bool lastQuoteCanBeLiteral = false;
    for (unsigned i = 0; i < format.length(); ++i) {
        UChar ch = format[i];
        if (inQuote) {
            if (ch == '\'') {
                inQuote = false;
                ASSERT(i);
                if (lastQuoteCanBeLiteral && format[i - 1] == '\'') {
                    literalBuffer.append('\'');
                    lastQuoteCanBeLiteral = false;
                } else
                    lastQuoteCanBeLiteral = true;
            } else
                literalBuffer.append(ch);
            continue;
        }

        if (ch == '\'') {
            inQuote = true;
            if (lastQuoteCanBeLiteral && i > 0 && format[i - 1] == '\'') {
                literalBuffer.append(ch);
                lastQuoteCanBeLiteral = false;
            } else
                lastQuoteCanBeLiteral = true;
        } else if (isASCIIAlpha(ch)) {
            commitLiteralToken(literalBuffer, converted);
            unsigned symbolStart = i;
            unsigned count = countContinuousLetters(format, i);
            i += count - 1;
            if (ch == 'h' || ch == 'H' || ch == 'm' || ch == 's' || ch == 'M' || ch == 'y')
                converted.append(format, symbolStart, count);
            else if (ch == 'd') {
                if (count <= 2)
                    converted.append(format, symbolStart, count);
                else if (count == 3)
                    converted.append("EEE");
                else
                    converted.append("EEEE");
            } else if (ch == 'g') {
                if (count == 1)
                    converted.append('G');
                else {
                    // gg means imperial era in Windows.
                    // Just ignore it.
                }
            } else if (ch == 't')
                converted.append('a');
            else
                literalBuffer.append(format, symbolStart, count);
        } else
            literalBuffer.append(ch);
    }
    commitLiteralToken(literalBuffer, converted);
    return converted.toString();
}
Exemple #2
0
// See http://msdn.microsoft.com/en-us/library/dd317787(v=vs.85).aspx
static Vector<DateFormatToken> parseDateFormat(const String format)
{
    Vector<DateFormatToken> tokens;
    StringBuilder literalBuffer;
    bool inQuote = false;
    for (unsigned i = 0; i < format.length(); ++i) {
        UChar ch = format[i];
        if (inQuote) {
            if (ch == '\'') {
                inQuote = false;
                ASSERT(i);
                if (format[i - 1] == '\'')
                    literalBuffer.append('\'');
            } else
                literalBuffer.append(ch);
            continue;
        }

        if (ch == '\'') {
            inQuote = true;
            if (i > 0 && format[i - 1] == '\'')
                literalBuffer.append(ch);
        } else if (isYearSymbol(ch)) {
            commitLiteralToken(literalBuffer, tokens);
            unsigned count = countContinuousLetters(format, i);
            i += count - 1;
            if (count == 1)
                tokens.append(DateFormatToken(DateFormatToken::Year1));
            else if (count == 2)
                tokens.append(DateFormatToken(DateFormatToken::Year2));
            else
                tokens.append(DateFormatToken(DateFormatToken::Year4));
        } else if (isMonthSymbol(ch)) {
            commitLiteralToken(literalBuffer, tokens);
            unsigned count = countContinuousLetters(format, i);
            i += count - 1;
            if (count == 1)
                tokens.append(DateFormatToken(DateFormatToken::Month1));
            else if (count == 2)
                tokens.append(DateFormatToken(DateFormatToken::Month2));
            else if (count == 3)
                tokens.append(DateFormatToken(DateFormatToken::Month3));
            else
                tokens.append(DateFormatToken(DateFormatToken::Month4));
        } else if (isDaySymbol(ch)) {
            commitLiteralToken(literalBuffer, tokens);
            unsigned count = countContinuousLetters(format, i);
            i += count - 1;
            if (count == 1)
                tokens.append(DateFormatToken(DateFormatToken::Day1));
            else
                tokens.append(DateFormatToken(DateFormatToken::Day2));
        } else if (isEraSymbol(ch)) {
            // Just ignore era.
            // HTML5 date supports only A.D.
        } else
            literalBuffer.append(ch);
    }
    commitLiteralToken(literalBuffer, tokens);
    return tokens;
}