diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp index 8f754549e87..f2a7eea0f89 100644 --- a/src/corelib/time/qtimezone.cpp +++ b/src/corelib/time/qtimezone.cpp @@ -1141,9 +1141,12 @@ bool QTimeZone::isDaylightTime(const QDateTime &atDateTime) const } /*! - Returns the effective offset details at the given \a forDateTime. This is - the equivalent of calling offsetFromUtc(), abbreviation(), etc individually but is - more efficient. + Returns the effective offset details at the given \a forDateTime. + + This is the equivalent of calling abbreviation() and all three offset + functions individually but is more efficient. If this data is not available + for the given datetime, an invalid OffsetData will be returned with an + invalid QDateTime as its \c atUtc. This method is only available when feature \c timezone is enabled. @@ -1163,9 +1166,9 @@ QTimeZone::OffsetData QTimeZone::offsetData(const QDateTime &forDateTime) const Q_UNREACHABLE(); break; } - } else if (hasTransitions()) { - return QTimeZonePrivate::toOffsetData(d->data(forDateTime.toMSecsSinceEpoch())); } + if (isValid()) + return QTimeZonePrivate::toOffsetData(d->data(forDateTime.toMSecsSinceEpoch())); return QTimeZonePrivate::invalidOffsetData(); } @@ -1206,7 +1209,7 @@ bool QTimeZone::hasTransitions() const Transition after it. If there is no transition after the given \a afterDateTime then an invalid - OffsetData will be returned with an invalid QDateTime. + OffsetData will be returned with an invalid QDateTime as its \c atUtc. The given \a afterDateTime is exclusive. @@ -1241,7 +1244,7 @@ QTimeZone::OffsetData QTimeZone::nextTransition(const QDateTime &afterDateTime) Transition before it. If there is no transition before the given \a beforeDateTime then an invalid - OffsetData will be returned with an invalid QDateTime. + OffsetData will be returned with an invalid QDateTime as its \c atUtc. The given \a beforeDateTime is exclusive. diff --git a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp index ea52033723e..8b9f5060dad 100644 --- a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp +++ b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp @@ -777,17 +777,29 @@ void tst_QTimeZone::transitionEachZone() void tst_QTimeZone::checkOffset_data() { - QTest::addColumn("zoneName"); + QTest::addColumn("zone"); QTest::addColumn("when"); QTest::addColumn("netOffset"); QTest::addColumn("stdOffset"); QTest::addColumn("dstOffset"); + const QTimeZone UTC = QTimeZone::UTC; + QTest::addRow("UTC") + << UTC << QDate(1970, 1, 1).startOfDay(UTC) << 0 << 0 << 0; + const auto east = QTimeZone::fromSecondsAheadOfUtc(28'800); // 8 hours + QTest::addRow("UTC+8") + << east << QDate(2000, 2, 29).startOfDay(east) << 28'800 << 28'800 << 0; + const auto west = QTimeZone::fromDurationAheadOfUtc(std::chrono::hours{-8}); + QTest::addRow("UTC-8") + << west << QDate(2100, 2, 28).startOfDay(west) << -28'800 << -28'800 << 0; + struct { const char *zone, *nick; int year, month, day, hour, min, sec; int std, dst; } table[] = { + // Exercise the UTC-backend: + { "UTC", "epoch", 1970, 1, 1, 0, 0, 0, 0, 0 }, // Zone with no transitions (QTBUG-74614, QTBUG-74666, when TZ backend uses minimal data) { "Etc/UTC", "epoch", 1970, 1, 1, 0, 0, 0, 0, 0 }, { "Etc/UTC", "pre_int32", 1901, 12, 13, 20, 45, 51, 0, 0 }, @@ -799,38 +811,40 @@ void tst_QTimeZone::checkOffset_data() { "Europe/Kiev", "summer", 2017, 10, 27, 12, 0, 0, 2 * 3600, 3600 }, { "Europe/Kiev", "winter", 2017, 10, 29, 12, 0, 0, 2 * 3600, 0 } }; - bool lacksRows = true; for (const auto &entry : table) { QTimeZone zone(entry.zone); if (zone.isValid()) { QTest::addRow("%s@%s", entry.zone, entry.nick) - << QByteArray(entry.zone) + << zone << QDateTime(QDate(entry.year, entry.month, entry.day), QTime(entry.hour, entry.min, entry.sec), zone) << entry.dst + entry.std << entry.std << entry.dst; - lacksRows = false; } else { qWarning("Skipping %s@%s test as zone is invalid", entry.zone, entry.nick); } } - if (lacksRows) - QSKIP("No valid zone info found, skipping test"); } void tst_QTimeZone::checkOffset() { - QFETCH(QByteArray, zoneName); + QFETCH(QTimeZone, zone); QFETCH(QDateTime, when); QFETCH(int, netOffset); QFETCH(int, stdOffset); QFETCH(int, dstOffset); - QTimeZone zone(zoneName); QVERIFY(zone.isValid()); // It was when _data() added the row ! QCOMPARE(zone.offsetFromUtc(when), netOffset); QCOMPARE(zone.standardTimeOffset(when), stdOffset); QCOMPARE(zone.daylightTimeOffset(when), dstOffset); QCOMPARE(zone.isDaylightTime(when), dstOffset != 0); + + // Also test offsetData(), which gets all this data in one go: + const auto data = zone.offsetData(when); + QCOMPARE(data.atUtc, when); + QCOMPARE(data.offsetFromUtc, netOffset); + QCOMPARE(data.standardTimeOffset, stdOffset); + QCOMPARE(data.daylightTimeOffset, dstOffset); } void tst_QTimeZone::availableTimeZoneIds()