diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 97d79f4b1e2..dd6fccd678b 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -728,10 +728,26 @@ /*! \enum Qt::TimeSpec - \value LocalTime Locale dependent time (Timezones and Daylight Savings Time). - \value UTC Coordinated Universal Time, replaces Greenwich Mean Time. + \value LocalTime Local time, controlled by a system time-zone setting. + \value UTC Coordinated Universal Time. \value OffsetFromUTC An offset in seconds from Coordinated Universal Time. - \value TimeZone A named time zone using a specific set of Daylight Savings rules. + \value TimeZone A named time zone. + + Both LocalTime and TimeZone will take care of transitions, such as + the start and end of daylight-saving time. UTC is the standard + time relative to which time-zones are usually specified: Greenwich + Mean Time has zero offset from it. Neither UTC nor OffsetFromUTC + has any transitions. + + \note After a change to the system time-zone setting, the behavior + of LocalTime-based QDateTime objects created before the change is + undefined: QDateTime may have cached data that the change + invalidates. (This is not triggered by transitions of the system + time-zone.) In long-running processes, updates to the system's + time-zone data (e.g. when politicians change the rules for a zone) + may likewise lead to conflicts between the updated time-zone + information and data cached by QDateTime objects created before + the update, using either LocalTime or TimeZone. */ /*! diff --git a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp index 146c6b37a5c..700524364eb 100644 --- a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -141,6 +141,7 @@ private Q_SLOTS: void isDaylightTime() const; void daylightTransitions() const; void timeZones() const; + void systemTimeZoneChange_data() const; void systemTimeZoneChange() const; void invalid_data() const; @@ -3798,35 +3799,60 @@ void tst_QDateTime::timeZones() const #endif } +void tst_QDateTime::systemTimeZoneChange_data() const +{ + QTest::addColumn("date"); + QTest::newRow("short") << QDate(1970, 1, 1); + QTest::newRow("2012") << QDate(2012, 6, 1); // short on 64-bit, pimpled on 32-bit + QTest::newRow("pimpled") << QDate(1150000, 6, 1); +} + void tst_QDateTime::systemTimeZoneChange() const { - // Set the timezone to Brisbane time + QFETCH(const QDate, date); + const QTime early(2, 15, 30); + + // Start out in Brisbane time: TimeZoneRollback useZone(QByteArray("AEST-10:00")); - - QDateTime localDate = QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::LocalTime); - QDateTime utcDate = QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::UTC); + if (QDateTime(date, early, Qt::LocalTime).offsetFromUtc() != 600 * 60) + QSKIP("Test depends on system support for changing zone to AEST-10:00"); #if QT_CONFIG(timezone) - QDateTime tzDate = QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), QTimeZone("Australia/Brisbane")); + QVERIFY(QTimeZone::systemTimeZone().isValid()); #endif - qint64 localMsecs = localDate.toMSecsSinceEpoch(); - qint64 utcMsecs = utcDate.toMSecsSinceEpoch(); -#if QT_CONFIG(timezone) - qint64 tzMsecs = tzDate.toMSecsSinceEpoch(); - // check that Australia/Brisbane is known + const QDateTime localDate = QDateTime(date, early, Qt::LocalTime); + const QDateTime utcDate = QDateTime(date, early, Qt::UTC); + const qint64 localMsecs = localDate.toMSecsSinceEpoch(); + const qint64 utcMsecs = utcDate.toMSecsSinceEpoch(); +#if QT_CONFIG(timezone) + const QTimeZone aest("Australia/Brisbane"); // no transitions since 1992 + // Check that Australia/Brisbane is known: + QVERIFY(aest.isValid()); + const QDateTime tzDate = QDateTime(date, early, aest); + + // Check we got the right zone ! QVERIFY(tzDate.timeZone().isValid()); + QCOMPARE(tzDate.timeZone(), aest); + const qint64 tzMsecs = tzDate.toMSecsSinceEpoch(); #endif // Change to Indian time useZone.reset(QByteArray("IST-05:30")); + if (QDateTime(date, early, Qt::LocalTime).offsetFromUtc() != 330 * 60) + QSKIP("Test depends on system support for changing zone to IST-05:30"); +#if QT_CONFIG(timezone) + QVERIFY(QTimeZone::systemTimeZone().isValid()); +#endif - QCOMPARE(localDate, QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::LocalTime)); - QVERIFY(localMsecs != localDate.toMSecsSinceEpoch()); - QCOMPARE(utcDate, QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::UTC)); + QCOMPARE(localDate, QDateTime(date, early, Qt::LocalTime)); + // Note: localDate.toMSecsSinceEpoch() == localMsecs, unchanged, iff localDate is pimpled. + QVERIFY(localMsecs != QDateTime(date, early, Qt::LocalTime).toMSecsSinceEpoch()); + QCOMPARE(utcDate, QDateTime(date, early, Qt::UTC)); QCOMPARE(utcDate.toMSecsSinceEpoch(), utcMsecs); #if QT_CONFIG(timezone) - QCOMPARE(tzDate, QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), QTimeZone("Australia/Brisbane"))); QCOMPARE(tzDate.toMSecsSinceEpoch(), tzMsecs); + QCOMPARE(tzDate.timeZone(), aest); + QCOMPARE(tzDate, QDateTime(date, early, aest)); #endif }