diff options
Diffstat (limited to 'src/corelib/tools/qdatetime.cpp')
-rw-r--r-- | src/corelib/tools/qdatetime.cpp | 1716 |
1 files changed, 1 insertions, 1715 deletions
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index ab5a516e8a..6c8fb85233 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -41,6 +41,7 @@ #include "qplatformdefs.h" #include "private/qdatetime_p.h" +#include "private/qdatetimeparser_p.h" #include "qdatastream.h" #include "qset.h" @@ -61,15 +62,6 @@ # endif #endif -//#define QDATETIMEPARSER_DEBUG -#if defined (QDATETIMEPARSER_DEBUG) && !defined(QT_NO_DEBUG_STREAM) -# define QDTPDEBUG qDebug() << QString("%1:%2").arg(__FILE__).arg(__LINE__) -# define QDTPDEBUGN qDebug -#else -# define QDTPDEBUG if (false) qDebug() -# define QDTPDEBUGN if (false) qDebug -#endif - #if defined(Q_OS_MAC) #include <private/qcore_mac_p.h> #endif @@ -4460,1710 +4452,4 @@ uint qHash(const QTime &key, uint seed) Q_DECL_NOTHROW return qHash(QTime(0, 0, 0, 0).msecsTo(key), seed); } -#ifndef QT_BOOTSTRAPPED - -/*! - \internal - Gets the digit from a datetime. E.g. - - QDateTime var(QDate(2004, 02, 02)); - int digit = getDigit(var, Year); - // digit = 2004 -*/ - -int QDateTimeParser::getDigit(const QDateTime &t, int index) const -{ - if (index < 0 || index >= sectionNodes.size()) { -#ifndef QT_NO_DATESTRING - qWarning("QDateTimeParser::getDigit() Internal error (%s %d)", - qPrintable(t.toString()), index); -#else - qWarning("QDateTimeParser::getDigit() Internal error (%d)", index); -#endif - return -1; - } - const SectionNode &node = sectionNodes.at(index); - switch (node.type) { - case Hour24Section: case Hour12Section: return t.time().hour(); - case MinuteSection: return t.time().minute(); - case SecondSection: return t.time().second(); - case MSecSection: return t.time().msec(); - case YearSection2Digits: - case YearSection: return t.date().year(); - case MonthSection: return t.date().month(); - case DaySection: return t.date().day(); - case DayOfWeekSectionShort: - case DayOfWeekSectionLong: return t.date().day(); - case AmPmSection: return t.time().hour() > 11 ? 1 : 0; - - default: break; - } - -#ifndef QT_NO_DATESTRING - qWarning("QDateTimeParser::getDigit() Internal error 2 (%s %d)", - qPrintable(t.toString()), index); -#else - qWarning("QDateTimeParser::getDigit() Internal error 2 (%d)", index); -#endif - return -1; -} - -/*! - \internal - Sets a digit in a datetime. E.g. - - QDateTime var(QDate(2004, 02, 02)); - int digit = getDigit(var, Year); - // digit = 2004 - setDigit(&var, Year, 2005); - digit = getDigit(var, Year); - // digit = 2005 -*/ - -bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const -{ - if (index < 0 || index >= sectionNodes.size()) { -#ifndef QT_NO_DATESTRING - qWarning("QDateTimeParser::setDigit() Internal error (%s %d %d)", - qPrintable(v.toString()), index, newVal); -#else - qWarning("QDateTimeParser::setDigit() Internal error (%d %d)", index, newVal); -#endif - return false; - } - const SectionNode &node = sectionNodes.at(index); - - int year, month, day, hour, minute, second, msec; - year = v.date().year(); - month = v.date().month(); - day = v.date().day(); - hour = v.time().hour(); - minute = v.time().minute(); - second = v.time().second(); - msec = v.time().msec(); - - switch (node.type) { - case Hour24Section: case Hour12Section: hour = newVal; break; - case MinuteSection: minute = newVal; break; - case SecondSection: second = newVal; break; - case MSecSection: msec = newVal; break; - case YearSection2Digits: - case YearSection: year = newVal; break; - case MonthSection: month = newVal; break; - case DaySection: - case DayOfWeekSectionShort: - case DayOfWeekSectionLong: - if (newVal > 31) { - // have to keep legacy behavior. setting the - // date to 32 should return false. Setting it - // to 31 for february should return true - return false; - } - day = newVal; - break; - case AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break; - default: - qWarning("QDateTimeParser::setDigit() Internal error (%s)", - qPrintable(sectionName(node.type))); - break; - } - - if (!(node.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong))) { - if (day < cachedDay) - day = cachedDay; - const int max = QDate(year, month, 1).daysInMonth(); - if (day > max) { - day = max; - } - } - if (QDate::isValid(year, month, day) && QTime::isValid(hour, minute, second, msec)) { - v = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec); - return true; - } - return false; -} - - - -/*! - \ - - Returns the absolute maximum for a section -*/ - -int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const -{ - const SectionNode &sn = sectionNode(s); - switch (sn.type) { - case Hour24Section: - case Hour12Section: return 23; // this is special-cased in - // parseSection. We want it to be - // 23 for the stepBy case. - case MinuteSection: - case SecondSection: return 59; - case MSecSection: return 999; - case YearSection2Digits: - case YearSection: return 9999; // sectionMaxSize will prevent - // people from typing in a larger - // number in count == 2 sections. - // stepBy() will work on real years anyway - case MonthSection: return 12; - case DaySection: - case DayOfWeekSectionShort: - case DayOfWeekSectionLong: return cur.isValid() ? cur.date().daysInMonth() : 31; - case AmPmSection: return 1; - default: break; - } - qWarning("QDateTimeParser::absoluteMax() Internal error (%s)", - qPrintable(sectionName(sn.type))); - return -1; -} - -/*! - \internal - - Returns the absolute minimum for a section -*/ - -int QDateTimeParser::absoluteMin(int s) const -{ - const SectionNode &sn = sectionNode(s); - switch (sn.type) { - case Hour24Section: - case Hour12Section: - case MinuteSection: - case SecondSection: - case MSecSection: - case YearSection2Digits: - case YearSection: return 0; - case MonthSection: - case DaySection: - case DayOfWeekSectionShort: - case DayOfWeekSectionLong: return 1; - case AmPmSection: return 0; - default: break; - } - qWarning("QDateTimeParser::absoluteMin() Internal error (%s, %0x)", - qPrintable(sectionName(sn.type)), sn.type); - return -1; -} - -/*! - \internal - - Returns the sectionNode for the Section \a s. -*/ - -const QDateTimeParser::SectionNode &QDateTimeParser::sectionNode(int sectionIndex) const -{ - if (sectionIndex < 0) { - switch (sectionIndex) { - case FirstSectionIndex: - return first; - case LastSectionIndex: - return last; - case NoSectionIndex: - return none; - } - } else if (sectionIndex < sectionNodes.size()) { - return sectionNodes.at(sectionIndex); - } - - qWarning("QDateTimeParser::sectionNode() Internal error (%d)", - sectionIndex); - return none; -} - -QDateTimeParser::Section QDateTimeParser::sectionType(int sectionIndex) const -{ - return sectionNode(sectionIndex).type; -} - - -/*! - \internal - - Returns the starting position for section \a s. -*/ - -int QDateTimeParser::sectionPos(int sectionIndex) const -{ - return sectionPos(sectionNode(sectionIndex)); -} - -int QDateTimeParser::sectionPos(const SectionNode &sn) const -{ - switch (sn.type) { - case FirstSection: return 0; - case LastSection: return displayText().size() - 1; - default: break; - } - if (sn.pos == -1) { - qWarning("QDateTimeParser::sectionPos Internal error (%s)", qPrintable(sectionName(sn.type))); - return -1; - } - return sn.pos; -} - - -/*! - \internal - - helper function for parseFormat. removes quotes that are - not escaped and removes the escaping on those that are escaped - -*/ - -static QString unquote(const QString &str) -{ - const QChar quote(QLatin1Char('\'')); - const QChar slash(QLatin1Char('\\')); - const QChar zero(QLatin1Char('0')); - QString ret; - QChar status(zero); - const int max = str.size(); - for (int i=0; i<max; ++i) { - if (str.at(i) == quote) { - if (status != quote) { - status = quote; - } else if (!ret.isEmpty() && str.at(i - 1) == slash) { - ret[ret.size() - 1] = quote; - } else { - status = zero; - } - } else { - ret += str.at(i); - } - } - return ret; -} -/*! - \internal - - Parses the format \a newFormat. If successful, returns true and - sets up the format. Else keeps the old format and returns false. - -*/ - -static inline int countRepeat(const QString &str, int index, int maxCount) -{ - int count = 1; - const QChar ch(str.at(index)); - const int max = qMin(index + maxCount, str.size()); - while (index + count < max && str.at(index + count) == ch) { - ++count; - } - return count; -} - -static inline void appendSeparator(QStringList *list, const QString &string, int from, int size, int lastQuote) -{ - QString str(string.mid(from, size)); - if (lastQuote >= from) - str = unquote(str); - list->append(str); -} - - -bool QDateTimeParser::parseFormat(const QString &newFormat) -{ - const QLatin1Char quote('\''); - const QLatin1Char slash('\\'); - const QLatin1Char zero('0'); - if (newFormat == displayFormat && !newFormat.isEmpty()) { - return true; - } - - QDTPDEBUGN("parseFormat: %s", newFormat.toLatin1().constData()); - - QVector<SectionNode> newSectionNodes; - Sections newDisplay = 0; - QStringList newSeparators; - int i, index = 0; - int add = 0; - QChar status(zero); - const int max = newFormat.size(); - int lastQuote = -1; - for (i = 0; i<max; ++i) { - if (newFormat.at(i) == quote) { - lastQuote = i; - ++add; - if (status != quote) { - status = quote; - } else if (newFormat.at(i - 1) != slash) { - status = zero; - } - } else if (status != quote) { - const char sect = newFormat.at(i).toLatin1(); - switch (sect) { - case 'H': - case 'h': - if (parserType != QVariant::Date) { - const Section hour = (sect == 'h') ? Hour12Section : Hour24Section; - const SectionNode sn = { hour, i - add, countRepeat(newFormat, i, 2), 0 }; - newSectionNodes.append(sn); - appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); - i += sn.count - 1; - index = i + 1; - newDisplay |= hour; - } - break; - case 'm': - if (parserType != QVariant::Date) { - const SectionNode sn = { MinuteSection, i - add, countRepeat(newFormat, i, 2), 0 }; - newSectionNodes.append(sn); - appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); - i += sn.count - 1; - index = i + 1; - newDisplay |= MinuteSection; - } - break; - case 's': - if (parserType != QVariant::Date) { - const SectionNode sn = { SecondSection, i - add, countRepeat(newFormat, i, 2), 0 }; - newSectionNodes.append(sn); - appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); - i += sn.count - 1; - index = i + 1; - newDisplay |= SecondSection; - } - break; - - case 'z': - if (parserType != QVariant::Date) { - const SectionNode sn = { MSecSection, i - add, countRepeat(newFormat, i, 3) < 3 ? 1 : 3, 0 }; - newSectionNodes.append(sn); - appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); - i += sn.count - 1; - index = i + 1; - newDisplay |= MSecSection; - } - break; - case 'A': - case 'a': - if (parserType != QVariant::Date) { - const bool cap = (sect == 'A'); - const SectionNode sn = { AmPmSection, i - add, (cap ? 1 : 0), 0 }; - newSectionNodes.append(sn); - appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); - newDisplay |= AmPmSection; - if (i + 1 < newFormat.size() - && newFormat.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) { - ++i; - } - index = i + 1; - } - break; - case 'y': - if (parserType != QVariant::Time) { - const int repeat = countRepeat(newFormat, i, 4); - if (repeat >= 2) { - const SectionNode sn = { repeat == 4 ? YearSection : YearSection2Digits, - i - add, repeat == 4 ? 4 : 2, 0 }; - newSectionNodes.append(sn); - appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); - i += sn.count - 1; - index = i + 1; - newDisplay |= sn.type; - } - } - break; - case 'M': - if (parserType != QVariant::Time) { - const SectionNode sn = { MonthSection, i - add, countRepeat(newFormat, i, 4), 0 }; - newSectionNodes.append(sn); - newSeparators.append(unquote(newFormat.mid(index, i - index))); - i += sn.count - 1; - index = i + 1; - newDisplay |= MonthSection; - } - break; - case 'd': - if (parserType != QVariant::Time) { - const int repeat = countRepeat(newFormat, i, 4); - const Section sectionType = (repeat == 4 ? DayOfWeekSectionLong - : (repeat == 3 ? DayOfWeekSectionShort : DaySection)); - const SectionNode sn = { sectionType, i - add, repeat, 0 }; - newSectionNodes.append(sn); - appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); - i += sn.count - 1; - index = i + 1; - newDisplay |= sn.type; - } - break; - - default: - break; - } - } - } - if (newSectionNodes.isEmpty() && context == DateTimeEdit) { - return false; - } - - if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) { - const int max = newSectionNodes.size(); - for (int i=0; i<max; ++i) { - SectionNode &node = newSectionNodes[i]; - if (node.type == Hour12Section) - node.type = Hour24Section; - } - } - - if (index < newFormat.size()) { - appendSeparator(&newSeparators, newFormat, index, index - max, lastQuote); - } else { - newSeparators.append(QString()); - } - - displayFormat = newFormat; - separators = newSeparators; - sectionNodes = newSectionNodes; - display = newDisplay; - last.pos = -1; - -// for (int i=0; i<sectionNodes.size(); ++i) { -// QDTPDEBUG << sectionName(sectionNodes.at(i).type) << sectionNodes.at(i).count; -// } - - QDTPDEBUG << newFormat << displayFormat; - QDTPDEBUGN("separators:\n'%s'", separators.join(QLatin1String("\n")).toLatin1().constData()); - - return true; -} - -/*! - \internal - - Returns the size of section \a s. -*/ - -int QDateTimeParser::sectionSize(int sectionIndex) const -{ - if (sectionIndex < 0) - return 0; - - if (sectionIndex >= sectionNodes.size()) { - qWarning("QDateTimeParser::sectionSize Internal error (%d)", sectionIndex); - return -1; - } - - if (sectionIndex == sectionNodes.size() - 1) { - // In some cases there is a difference between displayText() and text. - // e.g. when text is 2000/01/31 and displayText() is "2000/2/31" - text - // is the previous value and displayText() is the new value. - // The size difference is always due to leading zeroes. - int sizeAdjustment = 0; - if (displayText().size() != text.size()) { - // Any zeroes added before this section will affect our size. - int preceedingZeroesAdded = 0; - if (sectionNodes.size() > 1 && context == DateTimeEdit) { - for (QVector<SectionNode>::ConstIterator sectionIt = sectionNodes.constBegin(); - sectionIt != sectionNodes.constBegin() + sectionIndex; ++sectionIt) { - preceedingZeroesAdded += sectionIt->zeroesAdded; - } - } - sizeAdjustment = preceedingZeroesAdded; - } - - return displayText().size() + sizeAdjustment - sectionPos(sectionIndex) - separators.last().size(); - } else { - return sectionPos(sectionIndex + 1) - sectionPos(sectionIndex) - - separators.at(sectionIndex + 1).size(); - } -} - - -int QDateTimeParser::sectionMaxSize(Section s, int count) const -{ -#ifndef QT_NO_TEXTDATE - int mcount = 12; -#endif - - switch (s) { - case FirstSection: - case NoSection: - case LastSection: return 0; - - case AmPmSection: { - const int lowerMax = qMin(getAmPmText(AmText, LowerCase).size(), - getAmPmText(PmText, LowerCase).size()); - const int upperMax = qMin(getAmPmText(AmText, UpperCase).size(), - getAmPmText(PmText, UpperCase).size()); - return qMin(4, qMin(lowerMax, upperMax)); - } - - case Hour24Section: - case Hour12Section: - case MinuteSection: - case SecondSection: - case DaySection: return 2; - case DayOfWeekSectionShort: - case DayOfWeekSectionLong: -#ifdef QT_NO_TEXTDATE - return 2; -#else - mcount = 7; - // fall through -#endif - case MonthSection: - if (count <= 2) - return 2; - -#ifdef QT_NO_TEXTDATE - return 2; -#else - { - int ret = 0; - const QLocale l = locale(); - for (int i=1; i<=mcount; ++i) { - const QString str = (s == MonthSection - ? l.monthName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat) - : l.dayName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat)); - ret = qMax(str.size(), ret); - } - return ret; - } -#endif - case MSecSection: return 3; - case YearSection: return 4; - case YearSection2Digits: return 2; - - case CalendarPopupSection: - case Internal: - case TimeSectionMask: - case DateSectionMask: - qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s", - sectionName(s).toLatin1().constData()); - - case NoSectionIndex: - case FirstSectionIndex: - case LastSectionIndex: - case CalendarPopupIndex: - // these cases can't happen - break; - } - return -1; -} - - -int QDateTimeParser::sectionMaxSize(int index) const -{ - const SectionNode &sn = sectionNode(index); - return sectionMaxSize(sn.type, sn.count); -} - -/*! - \internal - - Returns the text of section \a s. This function operates on the - arg text rather than edit->text(). -*/ - - -QString QDateTimeParser::sectionText(const QString &text, int sectionIndex, int index) const -{ - const SectionNode &sn = sectionNode(sectionIndex); - switch (sn.type) { - case NoSectionIndex: - case FirstSectionIndex: - case LastSectionIndex: - return QString(); - default: break; - } - - return text.mid(index, sectionSize(sectionIndex)); -} - -QString QDateTimeParser::sectionText(int sectionIndex) const -{ - const SectionNode &sn = sectionNode(sectionIndex); - switch (sn.type) { - case NoSectionIndex: - case FirstSectionIndex: - case LastSectionIndex: - return QString(); - default: break; - } - - return displayText().mid(sn.pos, sectionSize(sectionIndex)); -} - - -#ifndef QT_NO_TEXTDATE -/*! - \internal:skipToNextSection - - Parses the part of \a text that corresponds to \a s and returns - the value of that field. Sets *stateptr to the right state if - stateptr != 0. -*/ - -int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionIndex, - QString &text, int &cursorPosition, int index, - State &state, int *usedptr) const -{ - state = Invalid; - int num = 0; - const SectionNode &sn = sectionNode(sectionIndex); - if ((sn.type & Internal) == Internal) { - qWarning("QDateTimeParser::parseSection Internal error (%s %d)", - qPrintable(sectionName(sn.type)), sectionIndex); - return -1; - } - - const int sectionmaxsize = sectionMaxSize(sectionIndex); - QString sectiontext = text.mid(index, sectionmaxsize); - int sectiontextSize = sectiontext.size(); - - QDTPDEBUG << "sectionValue for" << sectionName(sn.type) - << "with text" << text << "and st" << sectiontext - << text.mid(index, sectionmaxsize) - << index; - - int used = 0; - switch (sn.type) { - case AmPmSection: { - const int ampm = findAmPm(sectiontext, sectionIndex, &used); - switch (ampm) { - case AM: // sectiontext == AM - case PM: // sectiontext == PM - num = ampm; - state = Acceptable; - break; - case PossibleAM: // sectiontext => AM - case PossiblePM: // sectiontext => PM - num = ampm - 2; - state = Intermediate; - break; - case PossibleBoth: // sectiontext => AM|PM - num = 0; - state = Intermediate; - break; - case Neither: - state = Invalid; - QDTPDEBUG << "invalid because findAmPm(" << sectiontext << ") returned -1"; - break; - default: - QDTPDEBUGN("This should never happen (findAmPm returned %d)", ampm); - break; - } - if (state != Invalid) { - QString str = text; - text.replace(index, used, sectiontext.left(used)); - } - break; } - case MonthSection: - case DayOfWeekSectionShort: - case DayOfWeekSectionLong: - if (sn.count >= 3) { - if (sn.type == MonthSection) { - int min = 1; - const QDate minDate = getMinimum().date(); - if (currentValue.date().year() == minDate.year()) { - min = minDate.month(); - } - num = findMonth(sectiontext.toLower(), min, sectionIndex, §iontext, &used); - } else { - num = findDay(sectiontext.toLower(), 1, sectionIndex, §iontext, &used); - } - - if (num != -1) { - state = (used == sectiontext.size() ? Acceptable : Intermediate); - QString str = text; - text.replace(index, used, sectiontext.left(used)); - } else { - state = Intermediate; - } - break; } - // fall through - case DaySection: - case YearSection: - case YearSection2Digits: - case Hour12Section: - case Hour24Section: - case MinuteSection: - case SecondSection: - case MSecSection: { - if (sectiontextSize == 0) { - num = 0; - used = 0; - state = Intermediate; - } else { - const int absMax = absoluteMax(sectionIndex); - QLocale loc; - bool ok = true; - int last = -1; - used = -1; - - QString digitsStr(sectiontext); - for (int i = 0; i < sectiontextSize; ++i) { - if (digitsStr.at(i).isSpace()) { - sectiontextSize = i; - break; - } - } - - const int max = qMin(sectionmaxsize, sectiontextSize); - for (int digits = max; digits >= 1; --digits) { - digitsStr.truncate(digits); - int tmp = (int)loc.toUInt(digitsStr, &ok); - if (ok && sn.type == Hour12Section) { - if (tmp > 12) { - tmp = -1; - ok = false; - } else if (tmp == 12) { - tmp = 0; - } - } - if (ok && tmp <= absMax) { - QDTPDEBUG << sectiontext.left(digits) << tmp << digits; - last = tmp; - used = digits; - break; - } - } - - if (last == -1) { - QChar first(sectiontext.at(0)); - if (separators.at(sectionIndex + 1).startsWith(first)) { - used = 0; - state = Intermediate; - } else { - state = Invalid; - QDTPDEBUG << "invalid because" << sectiontext << "can't become a uint" << last << ok; - } - } else { - num += last; - const FieldInfo fi = fieldInfo(sectionIndex); - const bool done = (used == sectionmaxsize); - if (!done && fi & Fraction) { // typing 2 in a zzz field should be .200, not .002 - for (int i=used; i<sectionmaxsize; ++i) { - num *= 10; - } - } - const int absMin = absoluteMin(sectionIndex); - if (num < absMin) { - state = done ? Invalid : Intermediate; - if (done) - QDTPDEBUG << "invalid because" << num << "is less than absoluteMin" << absMin; - } else if (num > absMax) { - state = Intermediate; - } else if (!done && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) { - if (skipToNextSection(sectionIndex, currentValue, digitsStr)) { - state = Acceptable; - const int missingZeroes = sectionmaxsize - digitsStr.size(); - text.insert(index, QString().fill(QLatin1Char('0'), missingZeroes)); - used = sectionmaxsize; - cursorPosition += missingZeroes; - ++(const_cast<QDateTimeParser*>(this)->sectionNodes[sectionIndex].zeroesAdded); - } else { - state = Intermediate;; - } - } else { - state = Acceptable; - } - } - } - break; } - default: - qWarning("QDateTimeParser::parseSection Internal error (%s %d)", - qPrintable(sectionName(sn.type)), sectionIndex); - return -1; - } - - if (usedptr) - *usedptr = used; - - return (state != Invalid ? num : -1); -} -#endif // QT_NO_TEXTDATE - -#ifndef QT_NO_DATESTRING -/*! - \internal -*/ - -QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPosition, - const QDateTime ¤tValue, bool fixup) const -{ - const QDateTime minimum = getMinimum(); - const QDateTime maximum = getMaximum(); - - State state = Acceptable; - - QDateTime newCurrentValue; - int pos = 0; - bool conflicts = false; - const int sectionNodesCount = sectionNodes.size(); - - QDTPDEBUG << "parse" << input; - { - int year, month, day, hour12, hour, minute, second, msec, ampm, dayofweek, year2digits; - getDateFromJulianDay(currentValue.date().toJulianDay(), &year, &month, &day); - year2digits = year % 100; - hour = currentValue.time().hour(); - hour12 = -1; - minute = currentValue.time().minute(); - second = currentValue.time().second(); - msec = currentValue.time().msec(); - dayofweek = currentValue.date().dayOfWeek(); - - ampm = -1; - Sections isSet = NoSection; - int num; - State tmpstate; - - for (int index=0; state != Invalid && index<sectionNodesCount; ++index) { - if (QStringRef(&input, pos, separators.at(index).size()) != separators.at(index)) { - QDTPDEBUG << "invalid because" << input.mid(pos, separators.at(index).size()) - << "!=" << separators.at(index) - << index << pos << currentSectionIndex; - state = Invalid; - goto end; - } - pos += separators.at(index).size(); - sectionNodes[index].pos = pos; - int *current = 0; - const SectionNode sn = sectionNodes.at(index); - int used; - - num = parseSection(currentValue, index, input, cursorPosition, pos, tmpstate, &used); - QDTPDEBUG << "sectionValue" << sectionName(sectionType(index)) << input - << "pos" << pos << "used" << used << stateName(tmpstate); - if (fixup && tmpstate == Intermediate && used < sn.count) { - const FieldInfo fi = fieldInfo(index); - if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) { - const QString newText = QString::fromLatin1("%1").arg(num, sn.count, 10, QLatin1Char('0')); - input.replace(pos, used, newText); - used = sn.count; - } - } - pos += qMax(0, used); - - state = qMin<State>(state, tmpstate); - if (state == Intermediate && context == FromString) { - state = Invalid; - break; - } - - QDTPDEBUG << index << sectionName(sectionType(index)) << "is set to" - << pos << "state is" << stateName(state); - - - if (state != Invalid) { - switch (sn.type) { - case Hour24Section: current = &hour; break; - case Hour12Section: current = &hour12; break; - case MinuteSection: current = &minute; break; - case SecondSection: current = &second; break; - case MSecSection: current = &msec; break; - case YearSection: current = &year; break; - case YearSection2Digits: current = &year2digits; break; - case MonthSection: current = &month; break; - case DayOfWeekSectionShort: - case DayOfWeekSectionLong: current = &dayofweek; break; - case DaySection: current = &day; num = qMax<int>(1, num); break; - case AmPmSection: current = &m; break; - default: - qWarning("QDateTimeParser::parse Internal error (%s)", - qPrintable(sectionName(sn.type))); - break; - } - if (!current) { - qWarning("QDateTimeParser::parse Internal error 2"); - return StateNode(); - } - if (isSet & sn.type && *current != num) { - QDTPDEBUG << "CONFLICT " << sectionName(sn.type) << *current << num; - conflicts = true; - if (index != currentSectionIndex || num == -1) { - continue; - } - } - if (num != -1) - *current = num; - isSet |= sn.type; - } - } - - if (state != Invalid && QStringRef(&input, pos, input.size() - pos) != separators.last()) { - QDTPDEBUG << "invalid because" << input.mid(pos) - << "!=" << separators.last() << pos; - state = Invalid; - } - - if (state != Invalid) { - if (parserType != QVariant::Time) { - if (year % 100 != year2digits) { - switch (isSet & (YearSection2Digits|YearSection)) { - case YearSection2Digits: - year = (year / 100) * 100; - year += year2digits; - break; - case ((uint)YearSection2Digits|(uint)YearSection): { - conflicts = true; - const SectionNode &sn = sectionNode(currentSectionIndex); - if (sn.type == YearSection2Digits) { - year = (year / 100) * 100; - year += year2digits; - } - break; } - default: - break; - } - } - - const QDate date(year, month, day); - const int diff = dayofweek - date.dayOfWeek(); - if (diff != 0 && state == Acceptable && isSet & (DayOfWeekSectionShort|DayOfWeekSectionLong)) { - conflicts = isSet & DaySection; - const SectionNode &sn = sectionNode(currentSectionIndex); - if (sn.type & (DayOfWeekSectionShort|DayOfWeekSectionLong) || currentSectionIndex == -1) { - // dayofweek should be preferred - day += diff; - if (day <= 0) { - day += 7; - } else if (day > date.daysInMonth()) { - day -= 7; - } - QDTPDEBUG << year << month << day << dayofweek - << diff << QDate(year, month, day).dayOfWeek(); - } - } - bool needfixday = false; - if (sectionType(currentSectionIndex) & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong)) { - cachedDay = day; - } else if (cachedDay > day) { - day = cachedDay; - needfixday = true; - } - - if (!QDate::isValid(year, month, day)) { - if (day < 32) { - cachedDay = day; - } - if (day > 28 && QDate::isValid(year, month, 1)) { - needfixday = true; - } - } - if (needfixday) { - if (context == FromString) { - state = Invalid; - goto end; - } - if (state == Acceptable && fixday) { - day = qMin<int>(day, QDate(year, month, 1).daysInMonth()); - - const QLocale loc = locale(); - for (int i=0; i<sectionNodesCount; ++i) { - const Section thisSectionType = sectionType(i); - if (thisSectionType & (DaySection)) { - input.replace(sectionPos(i), sectionSize(i), loc.toString(day)); - } else if (thisSectionType & (DayOfWeekSectionShort|DayOfWeekSectionLong)) { - const int dayOfWeek = QDate(year, month, day).dayOfWeek(); - const QLocale::FormatType dayFormat = (thisSectionType == DayOfWeekSectionShort - ? QLocale::ShortFormat : QLocale::LongFormat); - const QString dayName(loc.dayName(dayOfWeek, dayFormat)); - input.replace(sectionPos(i), sectionSize(i), dayName); - } - } - } else { - state = qMin(Intermediate, state); - } - } - } - - if (parserType != QVariant::Date) { - if (isSet & Hour12Section) { - const bool hasHour = isSet & Hour24Section; - if (ampm == -1) { - if (hasHour) { - ampm = (hour < 12 ? 0 : 1); - } else { - ampm = 0; // no way to tell if this is am or pm so I assume am - } - } - hour12 = (ampm == 0 ? hour12 % 12 : (hour12 % 12) + 12); - if (!hasHour) { - hour = hour12; - } else if (hour != hour12) { - conflicts = true; - } - } else if (ampm != -1) { - if (!(isSet & (Hour24Section))) { - hour = (12 * ampm); // special case. Only ap section - } else if ((ampm == 0) != (hour < 12)) { - conflicts = true; - } - } - - } - - newCurrentValue = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec); - QDTPDEBUG << year << month << day << hour << minute << second << msec; - } - QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(), - newCurrentValue.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")).toLatin1().constData(), - stateName(state).toLatin1().constData()); - } -end: - if (newCurrentValue.isValid()) { - if (context != FromString && state != Invalid && newCurrentValue < minimum) { - const QLatin1Char space(' '); - if (newCurrentValue >= minimum) - qWarning("QDateTimeParser::parse Internal error 3 (%s %s)", - qPrintable(newCurrentValue.toString()), qPrintable(minimum.toString())); - - bool done = false; - state = Invalid; - for (int i=0; i<sectionNodesCount && !done; ++i) { - const SectionNode &sn = sectionNodes.at(i); - QString t = sectionText(input, i, sn.pos).toLower(); - if ((t.size() < sectionMaxSize(i) && (((int)fieldInfo(i) & (FixedWidth|Numeric)) != Numeric)) - || t.contains(space)) { - switch (sn.type) { - case AmPmSection: - switch (findAmPm(t, i)) { - case AM: - case PM: - state = Acceptable; - done = true; - break; - case Neither: - state = Invalid; - done = true; - break; - case PossibleAM: - case PossiblePM: - case PossibleBoth: { - const QDateTime copy(newCurrentValue.addSecs(12 * 60 * 60)); - if (copy >= minimum && copy <= maximum) { - state = Intermediate; - done = true; - } - break; } - } - case MonthSection: - if (sn.count >= 3) { - int tmp = newCurrentValue.date().month(); - // I know the first possible month makes the date too early - while ((tmp = findMonth(t, tmp + 1, i)) != -1) { - const QDateTime copy(newCurrentValue.addMonths(tmp - newCurrentValue.date().month())); - if (copy >= minimum && copy <= maximum) - break; // break out of while - } - if (tmp == -1) { - break; - } - state = Intermediate; - done = true; - break; - } - // fallthrough - default: { - int toMin; - int toMax; - - if (sn.type & TimeSectionMask) { - if (newCurrentValue.daysTo(minimum) != 0) { - break; - } - toMin = newCurrentValue.time().msecsTo(minimum.time()); - if (newCurrentValue.daysTo(maximum) > 0) { - toMax = -1; // can't get to max - } else { - toMax = newCurrentValue.time().msecsTo(maximum.time()); - } - } else { - toMin = newCurrentValue.daysTo(minimum); - toMax = newCurrentValue.daysTo(maximum); - } - const int maxChange = QDateTimeParser::maxChange(i); - if (toMin > maxChange) { - QDTPDEBUG << "invalid because toMin > maxChange" << toMin - << maxChange << t << newCurrentValue << minimum; - state = Invalid; - done = true; - break; - } else if (toMax > maxChange) { - toMax = -1; // can't get to max - } - - const int min = getDigit(minimum, i); - if (min == -1) { - qWarning("QDateTimeParser::parse Internal error 4 (%s)", - qPrintable(sectionName(sn.type))); - state = Invalid; - done = true; - break; - } - - int max = toMax != -1 ? getDigit(maximum, i) : absoluteMax(i, newCurrentValue); - int pos = cursorPosition - sn.pos; - if (pos < 0 || pos >= t.size()) - pos = -1; - if (!potentialValue(t.simplified(), min, max, i, newCurrentValue, pos)) { - QDTPDEBUG << "invalid because potentialValue(" << t.simplified() << min << max - << sectionName(sn.type) << "returned" << toMax << toMin << pos; - state = Invalid; - done = true; - break; - } - state = Intermediate; - done = true; - break; } - } - } - } - } else { - if (context == FromString) { - // optimization - Q_ASSERT(getMaximum().date().toJulianDay() == 4642999); - if (newCurrentValue.date().toJulianDay() > 4642999) - state = Invalid; - } else { - if (newCurrentValue > getMaximum()) - state = Invalid; - } - - QDTPDEBUG << "not checking intermediate because newCurrentValue is" << newCurrentValue << getMinimum() << getMaximum(); - } - } - StateNode node; - node.input = input; - node.state = state; - node.conflicts = conflicts; - node.value = newCurrentValue.toTimeSpec(spec); - text = input; - return node; -} -#endif // QT_NO_DATESTRING - -#ifndef QT_NO_TEXTDATE -/*! - \internal - finds the first possible monthname that \a str1 can - match. Starting from \a index; str should already by lowered -*/ - -int QDateTimeParser::findMonth(const QString &str1, int startMonth, int sectionIndex, - QString *usedMonth, int *used) const -{ - int bestMatch = -1; - int bestCount = 0; - if (!str1.isEmpty()) { - const SectionNode &sn = sectionNode(sectionIndex); - if (sn.type != MonthSection) { - qWarning("QDateTimeParser::findMonth Internal error"); - return -1; - } - - QLocale::FormatType type = sn.count == 3 ? QLocale::ShortFormat : QLocale::LongFormat; - QLocale l = locale(); - - for (int month=startMonth; month<=12; ++month) { - QString str2 = l.monthName(month, type).toLower(); - - if (str1.startsWith(str2)) { - if (used) { - QDTPDEBUG << "used is set to" << str2.size(); - *used = str2.size(); - } - if (usedMonth) - *usedMonth = l.monthName(month, type); - - return month; - } - if (context == FromString) - continue; - - const int limit = qMin(str1.size(), str2.size()); - - QDTPDEBUG << "limit is" << limit << str1 << str2; - bool equal = true; - for (int i=0; i<limit; ++i) { - if (str1.at(i) != str2.at(i)) { - equal = false; - if (i > bestCount) { - bestCount = i; - bestMatch = month; - } - break; - } - } - if (equal) { - if (used) - *used = limit; - if (usedMonth) - *usedMonth = l.monthName(month, type); - return month; - } - } - if (usedMonth && bestMatch != -1) - *usedMonth = l.monthName(bestMatch, type); - } - if (used) { - QDTPDEBUG << "used is set to" << bestCount; - *used = bestCount; - } - return bestMatch; -} - -int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex, QString *usedDay, int *used) const -{ - int bestMatch = -1; - int bestCount = 0; - if (!str1.isEmpty()) { - const SectionNode &sn = sectionNode(sectionIndex); - if (!(sn.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong))) { - qWarning("QDateTimeParser::findDay Internal error"); - return -1; - } - const QLocale l = locale(); - for (int day=startDay; day<=7; ++day) { - const QString str2 = l.dayName(day, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat); - - if (str1.startsWith(str2.toLower())) { - if (used) - *used = str2.size(); - if (usedDay) { - *usedDay = str2; - } - return day; - } - if (context == FromString) - continue; - - const int limit = qMin(str1.size(), str2.size()); - bool found = true; - for (int i=0; i<limit; ++i) { - if (str1.at(i) != str2.at(i) && !str1.at(i).isSpace()) { - if (i > bestCount) { - bestCount = i; - bestMatch = day; - } - found = false; - break; - } - - } - if (found) { - if (used) - *used = limit; - if (usedDay) - *usedDay = str2; - - return day; - } - } - if (usedDay && bestMatch != -1) { - *usedDay = l.dayName(bestMatch, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat); - } - } - if (used) - *used = bestCount; - - return bestMatch; -} -#endif // QT_NO_TEXTDATE - -/*! - \internal - - returns - 0 if str == QDateTimeEdit::tr("AM") - 1 if str == QDateTimeEdit::tr("PM") - 2 if str can become QDateTimeEdit::tr("AM") - 3 if str can become QDateTimeEdit::tr("PM") - 4 if str can become QDateTimeEdit::tr("PM") and can become QDateTimeEdit::tr("AM") - -1 can't become anything sensible - -*/ - -int QDateTimeParser::findAmPm(QString &str, int index, int *used) const -{ - const SectionNode &s = sectionNode(index); - if (s.type != AmPmSection) { - qWarning("QDateTimeParser::findAmPm Internal error"); - return -1; - } - if (used) - *used = str.size(); - if (str.trimmed().isEmpty()) { - return PossibleBoth; - } - const QLatin1Char space(' '); - int size = sectionMaxSize(index); - - enum { - amindex = 0, - pmindex = 1 - }; - QString ampm[2]; - ampm[amindex] = getAmPmText(AmText, s.count == 1 ? UpperCase : LowerCase); - ampm[pmindex] = getAmPmText(PmText, s.count == 1 ? UpperCase : LowerCase); - for (int i=0; i<2; ++i) - ampm[i].truncate(size); - - QDTPDEBUG << "findAmPm" << str << ampm[0] << ampm[1]; - - if (str.indexOf(ampm[amindex], 0, Qt::CaseInsensitive) == 0) { - str = ampm[amindex]; - return AM; - } else if (str.indexOf(ampm[pmindex], 0, Qt::CaseInsensitive) == 0) { - str = ampm[pmindex]; - return PM; - } else if (context == FromString || (str.count(space) == 0 && str.size() >= size)) { - return Neither; - } - size = qMin(size, str.size()); - - bool broken[2] = {false, false}; - for (int i=0; i<size; ++i) { - if (str.at(i) != space) { - for (int j=0; j<2; ++j) { - if (!broken[j]) { - int index = ampm[j].indexOf(str.at(i)); - QDTPDEBUG << "looking for" << str.at(i) - << "in" << ampm[j] << "and got" << index; - if (index == -1) { - if (str.at(i).category() == QChar::Letter_Uppercase) { - index = ampm[j].indexOf(str.at(i).toLower()); - QDTPDEBUG << "trying with" << str.at(i).toLower() - << "in" << ampm[j] << "and got" << index; - } else if (str.at(i).category() == QChar::Letter_Lowercase) { - index = ampm[j].indexOf(str.at(i).toUpper()); - QDTPDEBUG << "trying with" << str.at(i).toUpper() - << "in" << ampm[j] << "and got" << index; - } - if (index == -1) { - broken[j] = true; - if (broken[amindex] && broken[pmindex]) { - QDTPDEBUG << str << "didn't make it"; - return Neither; - } - continue; - } else { - str[i] = ampm[j].at(index); // fix case - } - } - ampm[j].remove(index, 1); - } - } - } - } - if (!broken[pmindex] && !broken[amindex]) - return PossibleBoth; - return (!broken[amindex] ? PossibleAM : PossiblePM); -} - -/*! - \internal - Max number of units that can be changed by this section. -*/ - -int QDateTimeParser::maxChange(int index) const -{ - const SectionNode &sn = sectionNode(index); - switch (sn.type) { - // Time. unit is msec - case MSecSection: return 999; - case SecondSection: return 59 * 1000; - case MinuteSection: return 59 * 60 * 1000; - case Hour24Section: case Hour12Section: return 59 * 60 * 60 * 1000; - - // Date. unit is day - case DayOfWeekSectionShort: - case DayOfWeekSectionLong: return 7; - case DaySection: return 30; - case MonthSection: return 365 - 31; - case YearSection: return 9999 * 365; - case YearSection2Digits: return 100 * 365; - default: - qWarning("QDateTimeParser::maxChange() Internal error (%s)", - qPrintable(sectionName(sectionType(index)))); - } - - return -1; -} - -QDateTimeParser::FieldInfo QDateTimeParser::fieldInfo(int index) const -{ - FieldInfo ret = 0; - const SectionNode &sn = sectionNode(index); - const Section s = sn.type; - switch (s) { - case MSecSection: - ret |= Fraction; - // fallthrough - case SecondSection: - case MinuteSection: - case Hour24Section: - case Hour12Section: - case YearSection: - case YearSection2Digits: - ret |= Numeric; - if (s != YearSection) { - ret |= AllowPartial; - } - if (sn.count != 1) { - ret |= FixedWidth; - } - break; - case MonthSection: - case DaySection: - switch (sn.count) { - case 2: - ret |= FixedWidth; - // fallthrough - case 1: - ret |= (Numeric|AllowPartial); - break; - } - break; - case DayOfWeekSectionShort: - case DayOfWeekSectionLong: - if (sn.count == 3) - ret |= FixedWidth; - break; - case AmPmSection: - ret |= FixedWidth; - break; - default: - qWarning("QDateTimeParser::fieldInfo Internal error 2 (%d %s %d)", - index, qPrintable(sectionName(sn.type)), sn.count); - break; - } - return ret; -} - -/*! - \internal - - Get a number that str can become which is between min - and max or -1 if this is not possible. -*/ - - -QString QDateTimeParser::sectionFormat(int index) const -{ - const SectionNode &sn = sectionNode(index); - return sectionFormat(sn.type, sn.count); -} - -QString QDateTimeParser::sectionFormat(Section s, int count) const -{ - QChar fillChar; - switch (s) { - case AmPmSection: return count == 1 ? QLatin1String("AP") : QLatin1String("ap"); - case MSecSection: fillChar = QLatin1Char('z'); break; - case SecondSection: fillChar = QLatin1Char('s'); break; - case MinuteSection: fillChar = QLatin1Char('m'); break; - case Hour24Section: fillChar = QLatin1Char('H'); break; - case Hour12Section: fillChar = QLatin1Char('h'); break; - case DayOfWeekSectionShort: - case DayOfWeekSectionLong: - case DaySection: fillChar = QLatin1Char('d'); break; - case MonthSection: fillChar = QLatin1Char('M'); break; - case YearSection2Digits: - case YearSection: fillChar = QLatin1Char('y'); break; - default: - qWarning("QDateTimeParser::sectionFormat Internal error (%s)", - qPrintable(sectionName(s))); - return QString(); - } - if (fillChar.isNull()) { - qWarning("QDateTimeParser::sectionFormat Internal error 2"); - return QString(); - } - - QString str; - str.fill(fillChar, count); - return str; -} - - -/*! - \internal - - Returns true if str can be modified to represent a - number that is within min and max. -*/ - -bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int index, - const QDateTime ¤tValue, int insert) const -{ - if (str.isEmpty()) { - return true; - } - const int size = sectionMaxSize(index); - int val = (int)locale().toUInt(str); - const SectionNode &sn = sectionNode(index); - if (sn.type == YearSection2Digits) { - val += currentValue.date().year() - (currentValue.date().year() % 100); - } - if (val >= min && val <= max && str.size() == size) { - return true; - } else if (val > max) { - return false; - } else if (str.size() == size && val < min) { - return false; - } - - const int len = size - str.size(); - for (int i=0; i<len; ++i) { - for (int j=0; j<10; ++j) { - if (potentialValue(str + QLatin1Char('0' + j), min, max, index, currentValue, insert)) { - return true; - } else if (insert >= 0) { - QString tmp = str; - tmp.insert(insert, QLatin1Char('0' + j)); - if (potentialValue(tmp, min, max, index, currentValue, insert)) - return true; - } - } - } - - return false; -} - -bool QDateTimeParser::skipToNextSection(int index, const QDateTime ¤t, const QString &text) const -{ - Q_ASSERT(current >= getMinimum() && current <= getMaximum()); - - const SectionNode &node = sectionNode(index); - Q_ASSERT(text.size() < sectionMaxSize(index)); - - const QDateTime maximum = getMaximum(); - const QDateTime minimum = getMinimum(); - QDateTime tmp = current; - int min = absoluteMin(index); - setDigit(tmp, index, min); - if (tmp < minimum) { - min = getDigit(minimum, index); - } - - int max = absoluteMax(index, current); - setDigit(tmp, index, max); - if (tmp > maximum) { - max = getDigit(maximum, index); - } - int pos = cursorPosition() - node.pos; - if (pos < 0 || pos >= text.size()) - pos = -1; - - const bool potential = potentialValue(text, min, max, index, current, pos); - return !potential; - - /* If the value potentially can become another valid entry we - * don't want to skip to the next. E.g. In a M field (month - * without leading 0 if you type 1 we don't want to autoskip but - * if you type 3 we do - */ -} - -/*! - \internal - For debugging. Returns the name of the section \a s. -*/ - -QString QDateTimeParser::sectionName(int s) const -{ - switch (s) { - case QDateTimeParser::AmPmSection: return QLatin1String("AmPmSection"); - case QDateTimeParser::DaySection: return QLatin1String("DaySection"); - case QDateTimeParser::DayOfWeekSectionShort: return QLatin1String("DayOfWeekSectionShort"); - case QDateTimeParser::DayOfWeekSectionLong: return QLatin1String("DayOfWeekSectionLong"); - case QDateTimeParser::Hour24Section: return QLatin1String("Hour24Section"); - case QDateTimeParser::Hour12Section: return QLatin1String("Hour12Section"); - case QDateTimeParser::MSecSection: return QLatin1String("MSecSection"); - case QDateTimeParser::MinuteSection: return QLatin1String("MinuteSection"); - case QDateTimeParser::MonthSection: return QLatin1String("MonthSection"); - case QDateTimeParser::SecondSection: return QLatin1String("SecondSection"); - case QDateTimeParser::YearSection: return QLatin1String("YearSection"); - case QDateTimeParser::YearSection2Digits: return QLatin1String("YearSection2Digits"); - case QDateTimeParser::NoSection: return QLatin1String("NoSection"); - case QDateTimeParser::FirstSection: return QLatin1String("FirstSection"); - case QDateTimeParser::LastSection: return QLatin1String("LastSection"); - default: return QLatin1String("Unknown section ") + QString::number(s); - } -} - -/*! - \internal - For debugging. Returns the name of the state \a s. -*/ - -QString QDateTimeParser::stateName(int s) const -{ - switch (s) { - case Invalid: return QLatin1String("Invalid"); - case Intermediate: return QLatin1String("Intermediate"); - case Acceptable: return QLatin1String("Acceptable"); - default: return QLatin1String("Unknown state ") + QString::number(s); - } -} - -#ifndef QT_NO_DATESTRING -bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const -{ - QDateTime val(QDate(1900, 1, 1), QDATETIMEEDIT_TIME_MIN); - QString text = t; - int copy = -1; - const StateNode tmp = parse(text, copy, val, false); - if (tmp.state != Acceptable || tmp.conflicts) { - return false; - } - if (time) { - const QTime t = tmp.value.time(); - if (!t.isValid()) { - return false; - } - *time = t; - } - - if (date) { - const QDate d = tmp.value.date(); - if (!d.isValid()) { - return false; - } - *date = d; - } - return true; -} -#endif // QT_NO_DATESTRING - -QDateTime QDateTimeParser::getMinimum() const -{ - return QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, spec); -} - -QDateTime QDateTimeParser::getMaximum() const -{ - return QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, spec); -} - -QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const -{ - if (ap == AmText) { - return (cs == UpperCase ? QLatin1String("AM") : QLatin1String("am")); - } else { - return (cs == UpperCase ? QLatin1String("PM") : QLatin1String("pm")); - } -} - -/* - \internal - - I give arg2 preference because arg1 is always a QDateTime. -*/ - -bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2) -{ - return (s1.type == s2.type) && (s1.pos == s2.pos) && (s1.count == s2.count); -} - -#endif // QT_BOOTSTRAPPED - QT_END_NAMESPACE |