double integerFromString(const QString &str, int radix)
{
    QByteArray ba = str.trimmed().toLatin1();
    return integerFromString(ba.constData(), ba.size(), radix);
}
示例#2
0
DateTimeComponents KDateTimeParser::parseDatePosix(const QString &inputString,
        const QString &formatString,
        const KCalendarSystem *calendar,
        const KLocale *locale,
        KLocale::DigitSet digitSet,
        KLocale::DateTimeFormatStandard standard) const
{
    QString str = inputString.simplified().toLower();
    QString fmt = formatString.simplified();
    int dd = -1;
    int mm = -1;
    int yy = 0;
    bool parsedYear = false;
    int ey = -1;
    QString ee;
    int dayInYear = -1;
    int isoWeekNumber = -1;
    int dayOfIsoWeek = -1;
    int strpos = 0;
    int fmtpos = 0;
    int readLength; // Temporary variable used when reading input
    bool error = false;

    while (fmt.length() > fmtpos && str.length() > strpos && !error) {

        QChar fmtChar = fmt.at(fmtpos++);

        if (fmtChar != QLatin1Char('%')) {

            if (fmtChar.isSpace() && str.at(strpos).isSpace()) {
                strpos++;
            } else if (fmtChar.toLower() == str.at(strpos)) {
                strpos++;
            } else {
                error = true;
            }

        } else {
            int j;
            QString shortName, longName;
            QChar modifierChar;
            // remove space at the beginning
            if (str.length() > strpos && str.at(strpos).isSpace()) {
                strpos++;
            }

            fmtChar = fmt.at(fmtpos++);
            if (fmtChar == QLatin1Char('E')) {
                modifierChar = fmtChar;
                fmtChar = fmt.at(fmtpos++);
            }

            switch (fmtChar.unicode()) {
            case 'a':  // Weekday Name Short
            case 'A':  // Weekday Name Long
                error = true;
                j = 1;
                while (error && j <= calendar->d_ptr->daysInWeek()) {
                    shortName = calendar->weekDayName(j, KCalendarSystem::ShortDayName).toLower();
                    longName = calendar->weekDayName(j, KCalendarSystem::LongDayName).toLower();
                    if (str.mid(strpos, longName.length()) == longName) {
                        strpos += longName.length();
                        error = false;
                    } else if (str.mid(strpos, shortName.length()) == shortName) {
                        strpos += shortName.length();
                        error = false;
                    }
                    ++j;
                }
                break;
            case 'b':  // Month Name Short
            case 'h':  // Month Name Short
            case 'B':  // Month Name Long
                error = true;
                j = 1;
                while (error && j <= calendar->d_ptr->maxMonthsInYear()) {
                    // This may be a problem in calendar systems with variable number of months
                    // in the year and/or names of months that change depending on the year, e.g
                    // Hebrew.  We really need to know the correct year first, but we may not have
                    // read it yet and will be using the current year instead
                    int monthYear;
                    if (parsedYear) {
                        monthYear = yy;
                    } else {
                        monthYear = calendar->year(QDate::currentDate());
                    }
                    if (calendar->locale()->dateMonthNamePossessive()) {
                        shortName = calendar->monthName(j, monthYear, KCalendarSystem::ShortNamePossessive).toLower();
                        longName = calendar->monthName(j, monthYear, KCalendarSystem::LongNamePossessive).toLower();
                    } else {
                        shortName = calendar->monthName(j, monthYear, KCalendarSystem::ShortName).toLower();
                        longName = calendar->monthName(j, monthYear, KCalendarSystem::LongName).toLower();
                    }
                    if (str.mid(strpos, longName.length()) == longName) {
                        mm = j;
                        strpos += longName.length();
                        error = false;
                    } else if (str.mid(strpos, shortName.length()) == shortName) {
                        mm = j;
                        strpos += shortName.length();
                        error = false;
                    }
                    ++j;
                }
                break;
            case 'd': // Day Number Long
            case 'e': // Day Number Short
                dd = calendar->dayStringToInteger(str.mid(strpos), readLength);
                strpos += readLength;
                error = readLength <= 0;
                break;
            case 'n':
                // PosixFormat %n is Newline
                // KdeFormat %n is Month Number Short
                if (standard == KLocale::KdeFormat) {
                    mm = calendar->monthStringToInteger(str.mid(strpos), readLength);
                    strpos += readLength;
                    error = readLength <= 0;
                }
                // standard == KLocale::PosixFormat
                // all whitespace already 'eaten', no action required
                break;
            case 'm': // Month Number Long
                mm = calendar->monthStringToInteger(str.mid(strpos), readLength);
                strpos += readLength;
                error = readLength <= 0;
                break;
            case 'Y': // Year Number Long
            case 'y': // Year Number Short
                if (modifierChar == QLatin1Char('E')) {    // Year In Era
                    if (fmtChar == QLatin1Char('y')) {
                        ey = calendar->yearStringToInteger(str.mid(strpos), readLength);
                        strpos += readLength;
                        error = readLength <= 0;
                    } else {
                        error = true;
                        j = calendar->eraList()->count() - 1; // Start with the most recent
                        while (error && j >= 0) {
                            QString subFormat = calendar->eraList()->at(j).format();
                            QString subInput = str.mid(strpos);
                            DateTimeComponents subResult = parseDatePosix(subInput, subFormat, calendar, locale, digitSet, standard);
                            if (!subResult.error) {
                                if (subResult.parsedYear) {
                                    yy = subResult.year;
                                    parsedYear = true;
                                    error = false;
                                    strpos += subResult.inputPosition;
                                } else if (!subResult.eraName.isEmpty() && subResult.yearInEra >= 0) {
                                    ee = subResult.eraName;
                                    ey = subResult.yearInEra;
                                    error = false;
                                    strpos += subResult.inputPosition;
                                }
                            }
                            --j;
                        }
                    }
                } else {
                    yy = calendar->yearStringToInteger(str.mid(strpos), readLength);
                    strpos += readLength;
                    if (fmtChar == QLatin1Char('y')) {
                        yy = calendar->applyShortYearWindow(yy);
                    }
                    error = readLength <= 0;
                    if (!error) {
                        parsedYear = true;
                    }
                }
                break;
            case 'C': // Era
                error = true;
                if (modifierChar == QLatin1Char('E')) {
                    j = calendar->eraList()->count() - 1; // Start with the most recent
                    while (error && j >= 0) {
                        shortName = calendar->d_ptr->m_eraList->at(j).name(KLocale::ShortName).toLower();
                        longName = calendar->eraList()->at(j).name(KLocale::LongName).toLower();
                        if (str.mid(strpos, longName.length()) == longName) {
                            strpos += longName.length();
                            ee = longName;
                            error = false;
                        } else if (str.mid(strpos, shortName.length()) == shortName) {
                            strpos += shortName.length();
                            ee = shortName;
                            error = false;
                        }
                        --j;
                    }
                }
                break;
            case 'j': // Day Of Year Number
                dayInYear = integerFromString(str.mid(strpos), 3, readLength);
                strpos += readLength;
                error = readLength <= 0;
                break;
            case 'V': // ISO Week Number
                isoWeekNumber = integerFromString(str.mid(strpos), 2, readLength);
                strpos += readLength;
                error = readLength <= 0;
                break;
            case 'u': // ISO Day Of Week
                dayOfIsoWeek = integerFromString(str.mid(strpos), 1, readLength);
                strpos += readLength;
                error = readLength <= 0;
                break;
            }
        }
    }

    DateTimeComponents result;
    result.error = error;
    result.inputPosition = strpos;
    result.formatPosition = fmtpos;
    if (error) {
        result.day = -1;
        result.month = -1;
        result.year = 0;
        result.parsedYear = false;
        result.eraName.clear();
        result.yearInEra = -1;
        result.dayInYear = -1;
        result.isoWeekNumber = -1;
        result.dayOfIsoWeek = -1;
    } else {
        result.day = dd;
        result.month = mm;
        result.year = yy;
        result.parsedYear = parsedYear;
        result.eraName = ee;
        result.yearInEra = ey;
        result.dayInYear = dayInYear;
        result.isoWeekNumber = isoWeekNumber;
        result.dayOfIsoWeek = dayOfIsoWeek;
    }
    return result;
}