diff options
author | Edward Welbourne <edward.welbourne@qt.io> | 2023-06-15 13:45:58 +0200 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2023-07-21 18:22:01 +0200 |
commit | ca6a0fd63fdd5209f2cc1ff59e6b31c0bed14597 (patch) | |
tree | 19d6ff3bc439fbfa96861bd40d581e2355f95c24 /tests/auto/corelib/time | |
parent | c888e3922d73df791f0f31553536abf03b241a65 (diff) |
QDTP: match local-time by preference to its zone
When parsing a string whose time-zone part matches local time's name,
use local time in preference to the QTimeZone with that name. The case
is ambiguous, and the bug was already fixed (by something else) in
dev, but this caused a failure in 6.2 through 6.5; and using local
time is more natural to QDateTime in any case. The fix incidentally
makes the the logic of the zone-resolution code more straightforward
and a closer match to how findTimeZone() found the match.
The issue was hidden from 6.6 by a change [*] to the handling of POSIX
rules, that lead to plain abbreviations such as CEST and BST - for
which the IANA DB has no entry - no longer being considered "valid"
zones, despite being technically valid POSIX zone descriptors
(effectively as aliases for UTC).
[*] commit 41c561ddde6210651c60c0789d592f79d7b3e4d5
Pick-to: 6.6 6.5 6.2
Fixes: QTBUG-114575
Change-Id: I4369901afd26961d038e382f4c4a7beb83659ad7
Reviewed-by: Konrad Kujawa <konrad.kujawa@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests/auto/corelib/time')
-rw-r--r-- | tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp | 9 | ||||
-rw-r--r-- | tests/auto/corelib/time/qdatetimeparser/tst_qdatetimeparser.cpp | 32 |
2 files changed, 39 insertions, 2 deletions
diff --git a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp index 7659c9722e..1054e5f968 100644 --- a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp @@ -7,7 +7,7 @@ #include <QTimeZone> #include <private/qdatetime_p.h> -#include <private/qtenvironmentvariables_p.h> // for qTzSet() +#include <private/qtenvironmentvariables_p.h> // for qTzSet(), qTzName() #ifdef Q_OS_WIN # include <qt_windows.h> @@ -3255,10 +3255,15 @@ void tst_QDateTime::fromStringStringFormat_localTimeZone_data() QTimeZone gmt("GMT"); if (gmt.isValid()) { lacksRows = false; + const bool fullyLocal = ([]() { + TimeZoneRollback useZone("GMT"); + return qTzName(0) == u"GMT"_s; + })(); QTest::newRow("local-timezone-with-offset:GMT") << QByteArrayLiteral("GMT") << QString("2008-10-13 GMT 11.50") << QString("yyyy-MM-dd t hh.mm") - << QDateTime(QDate(2008, 10, 13), QTime(11, 50), gmt); + << QDateTime(QDate(2008, 10, 13), QTime(11, 50), + fullyLocal ? QTimeZone(QTimeZone::LocalTime) : gmt); } QTimeZone helsinki("Europe/Helsinki"); if (helsinki.isValid()) { diff --git a/tests/auto/corelib/time/qdatetimeparser/tst_qdatetimeparser.cpp b/tests/auto/corelib/time/qdatetimeparser/tst_qdatetimeparser.cpp index 32753d895f..7f97e551a6 100644 --- a/tests/auto/corelib/time/qdatetimeparser/tst_qdatetimeparser.cpp +++ b/tests/auto/corelib/time/qdatetimeparser/tst_qdatetimeparser.cpp @@ -46,6 +46,7 @@ class tst_QDateTimeParser : public QObject Q_OBJECT private Q_SLOTS: + void reparse(); void parseSection_data(); void parseSection(); @@ -53,6 +54,37 @@ private Q_SLOTS: void intermediateYear(); }; +void tst_QDateTimeParser::reparse() +{ + const QDateTime when = QDate(2023, 6, 15).startOfDay(); + // QTBUG-114575: 6.2 through 6.5 got back a bogus Qt::TimeZone (with zero offset): + const Qt::TimeSpec spec = ([](QStringView name) { + // When local time is UTC or a fixed offset from it, the parser prefers + // to interpret a UTC or offset suffix as such, rather than as local + // time (thereby avoiding DST-ness checks). We have to match that here. + if (name == QLatin1StringView("UTC")) + return Qt::UTC; + if (name.startsWith(u'+') || name.startsWith(u'-')) { + if (std::all_of(name.begin() + 1, name.end(), [](QChar ch) { return ch == u'0'; })) + return Qt::UTC; + if (std::all_of(name.begin() + 1, name.end(), [](QChar ch) { return ch.isDigit(); })) + return Qt::OffsetFromUTC; + // Potential hh:mm offset ? Not yet seen as local tzname[] entry. + } + return Qt::LocalTime; + })(when.timeZoneAbbreviation()); + + const QStringView format = u"dd/MM/yyyy HH:mm t"; + QDateTimeParser who(QMetaType::QDateTime, QDateTimeParser::DateTimeEdit); + QVERIFY(who.parseFormat(format)); + const auto state = who.parse(when.toString(format), -1, when, false); + QCOMPARE(state.state, QDateTimeParser::Acceptable); + QVERIFY(!state.conflicts); + QCOMPARE(state.padded, 0); + QCOMPARE(state.value.timeSpec(), spec); + QCOMPARE(state.value, when); +} + void tst_QDateTimeParser::parseSection_data() { QTest::addColumn<QString>("format"); |