diff options
-rw-r--r-- | src/corelib/tools/qdatetime.cpp | 23 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp | 4 |
2 files changed, 20 insertions, 7 deletions
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 9d26207a0f..045ad10755 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -4720,25 +4720,35 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format) if (size < 10) return QDateTime(); - QStringRef isoString(&string); - Qt::TimeSpec spec = Qt::LocalTime; - QDate date = QDate::fromString(string.left(10), Qt::ISODate); if (!date.isValid()) return QDateTime(); if (size == 10) return QDateTime(date); - isoString = isoString.right(isoString.length() - 11); + Qt::TimeSpec spec = Qt::LocalTime; + QStringRef isoString(&string); + isoString = isoString.mid(10); // trim "yyyy-MM-dd" + + // Must be left with T and at least one digit for the hour: + if (isoString.size() < 2 + || !(isoString.startsWith(QLatin1Char('T')) + // FIXME: QSql relies on QVariant::toDateTime() accepting a space here: + || isoString.startsWith(QLatin1Char(' ')))) { + return QDateTime(); + } + isoString = isoString.mid(1); // trim 'T' (or space) + int offset = 0; // Check end of string for Time Zone definition, either Z for UTC or [+-]HH:mm for Offset if (isoString.endsWith(QLatin1Char('Z'))) { spec = Qt::UTC; - isoString = isoString.left(isoString.size() - 1); + isoString.chop(1); // trim 'Z' } else { // the loop below is faster but functionally equal to: // const int signIndex = isoString.indexOf(QRegExp(QStringLiteral("[+-]"))); int signIndex = isoString.size() - 1; + Q_ASSERT(signIndex >= 0); bool found = false; { const QChar plus = QLatin1Char('+'); @@ -4746,8 +4756,7 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format) do { QChar character(isoString.at(signIndex)); found = character == plus || character == minus; - } while (--signIndex >= 0 && !found); - ++signIndex; + } while (!found && --signIndex >= 0); } if (found) { diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index 28ad2d193c..91b5966fa8 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -2277,6 +2277,10 @@ void tst_QDateTime::fromStringDateFormat_data() QTest::newRow("ISO .99999 of a minute (comma)") << QString::fromLatin1("2012-01-01T08:00,99999") << Qt::ISODate << QDateTime(QDate(2012, 1, 1), QTime(8, 0, 59, 999), Qt::LocalTime); QTest::newRow("ISO empty") << QString::fromLatin1("") << Qt::ISODate << invalidDateTime(); + QTest::newRow("ISO short") << QString::fromLatin1("2017-07-01T") << Qt::ISODate << invalidDateTime(); + QTest::newRow("ISO zoned date") << QString::fromLatin1("2017-07-01Z") << Qt::ISODate << invalidDateTime(); + QTest::newRow("ISO zoned empty time") << QString::fromLatin1("2017-07-01TZ") << Qt::ISODate << invalidDateTime(); + QTest::newRow("ISO mis-punctuated") << QString::fromLatin1("2018/01/30 ") << Qt::ISODate << invalidDateTime(); // Test Qt::RFC2822Date format (RFC 2822). QTest::newRow("RFC 2822 +0100") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100") |