From 3d785249ba43cf4bd895ed679bac2791e0130dc5 Mon Sep 17 00:00:00 2001 From: Andreas Buhr Date: Fri, 27 Nov 2020 15:42:36 +0100 Subject: [PATCH] Restore previous QDateTime behavior in DST gap Historic QDateTime behavior when being asked to create a QDateTime in the DST gap was to interpret the given date as if it was in the time before that gap, mapping it to a point in time after the gap. This has changed with a04411119ead3d4473e4f0ac4bceedc585977b2f . Since then, the given date is interpreted as if it was in the time after the gap, thus being mapped to a point in time before the gap. This patch restores the historic behavior. This was not caught by Coin because machines ran in timezone "Atlantic/Reykjavik" which does not have DST since 1967. This patch changes tests to always run in "Europe/Oslo". Driveby: Test function "findSpring" did some operations in local time, even though being asked to work in a specific time zone. Fixed that. Fixes: QTBUG-86960 Fixes: QTBUG-89208 Pick-to: 6.0 5.15 Change-Id: Iecce5898bf9711a10e7dfc0a25e4bbeaed1c8ade Reviewed-by: Thiago Macieira --- src/corelib/time/qdatetime.cpp | 6 +++--- tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp | 5 +++++ tests/auto/widgets/widgets/qdatetimeedit/BLACKLIST | 4 ---- .../widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) delete mode 100644 tests/auto/widgets/widgets/qdatetimeedit/BLACKLIST diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index 757636ede2..5ed72dd5e3 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -2856,21 +2856,21 @@ static void refreshZonedDateTime(QDateTimeData &d, Qt::TimeSpec spec) qint64 epochMSecs = 0; QDate testDate; QTime testTime; + auto dstStatus = extractDaylightStatus(status); if (spec == Qt::LocalTime) { - auto dstStatus = extractDaylightStatus(status); epochMSecs = localMSecsToEpochMSecs(msecs, &dstStatus, &testDate, &testTime); - status = mergeDaylightStatus(status, dstStatus); #if QT_CONFIG(timezone) // else spec == Qt::TimeZone, so check zone is valid: } else if (d->m_timeZone.isValid()) { epochMSecs = QDateTimePrivate::zoneMSecsToEpochMSecs( - msecs, d->m_timeZone, extractDaylightStatus(status), &testDate, &testTime); + msecs, d->m_timeZone, dstStatus, &testDate, &testTime); #endif // timezone } // else: testDate, testTime haven't been set, so are invalid. // Cache the offset to use in offsetFromUtc() &c. offsetFromUtc = (msecs - epochMSecs) / 1000; if (testDate.isValid() && testTime.isValid() && timeToMSecs(testDate, testTime) == msecs) { + status = mergeDaylightStatus(status, dstStatus); status |= QDateTimePrivate::ValidDateTime; } else { status &= ~QDateTimePrivate::ValidDateTime; diff --git a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp index 44916e96f5..e28ae128c8 100644 --- a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp @@ -2826,6 +2826,9 @@ void tst_QDateTime::fromStringStringFormat() #endif // OffsetFromUTC needs an offset check - we may as well do it for all: QCOMPARE(dt.offsetFromUtc(), expected.offsetFromUtc()); + } else { + QCOMPARE(dt.isValid(), expected.isValid()); + QCOMPARE(dt.toMSecsSinceEpoch(), expected.toMSecsSinceEpoch()); } } @@ -3250,6 +3253,8 @@ void tst_QDateTime::daylightTransitions() const QVERIFY(!missing.isValid()); QCOMPARE(missing.date(), QDate(2012, 3, 25)); QCOMPARE(missing.time(), QTime(2, 0)); + // datetimeparser relies on toMSecsSinceEpoch to still work: + QCOMPARE(missing.toMSecsSinceEpoch(), daylight2012); QDateTime after(QDate(2012, 3, 25), QTime(3, 0)); QVERIFY(after.isValid()); diff --git a/tests/auto/widgets/widgets/qdatetimeedit/BLACKLIST b/tests/auto/widgets/widgets/qdatetimeedit/BLACKLIST deleted file mode 100644 index 1ded2ba0b3..0000000000 --- a/tests/auto/widgets/widgets/qdatetimeedit/BLACKLIST +++ /dev/null @@ -1,4 +0,0 @@ -[springForward] -opensuse-leap -[stepIntoDSTGap] -opensuse-leap diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp index b7ae7df5ed..05124d1ad6 100644 --- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp +++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp @@ -4622,7 +4622,7 @@ static QDateTime findSpring(int year, const QTimeZone &timeZone) return QDateTime(); // Southern hemisphere spring is after midsummer - const QDateTime midSummer = QDate(year, 6, 21).startOfDay(); + const QDateTime midSummer = QDate(year, 6, 21).startOfDay(timeZone); const QTimeZone::OffsetData transition = midSummer.isDaylightTime() ? timeZone.previousTransition(midSummer) : timeZone.nextTransition(midSummer); @@ -4744,7 +4744,7 @@ void tst_QDateTimeEdit::stepIntoDSTGap_data() QTest::addColumn("steps"); QTest::addColumn("end"); - const QTimeZone timeZone = QTimeZone::systemTimeZone(); + const QTimeZone timeZone = QTimeZone("Europe/Oslo"); if (!timeZone.hasDaylightTime()) QSKIP("This test needs to run in a timezone that observes DST!");