diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp index 44b6662b5b7..81b0a5efe7c 100644 --- a/src/corelib/time/qtimezone.cpp +++ b/src/corelib/time/qtimezone.cpp @@ -556,16 +556,12 @@ QTimeZone::QTimeZone(QTimeZonePrivate &dd) In all cases, the result's \l timeSpec() is Qt::TimeZone. When this QTimeZone's timeSpec() is Qt::TimeZone, this QTimeZone itself is returned. + If timeSpec() is Qt::LocalTime then systemTimeZone() is returned. If timeSpec() is Qt::UTC, QTimeZone::utc() is returned. If it is Qt::OffsetFromUTC then QTimeZone(int) is passed its offset and the result is returned. - If timeSpec() is Qt::LocalTime then an instance of the current system time - zone will be returned. This will not change to reflect any subsequent change - to the system time zone. It represents the local time that was in effect - when asBackendZone() was called. - When using a lightweight time representation - local time, UTC time or time at a fixed offset from UTC - using methods only supported when feature \c timezone is enabled may be more expensive than using a corresponding time @@ -1353,11 +1349,29 @@ QByteArray QTimeZone::systemTimeZoneId() representation \c {QTimeZone(QTimeZone::LocalTime)}, albeit implemented as a time zone. + The returned object will not change to reflect any subsequent change to the + system time zone. It represents the local time that was in effect when + asBackendZone() was called. On misconfigured systems, such as those that + lack the timezone data relied on by the backend for which Qt was compiled, + it may be invalid. In such a case, a warning is output. + \sa utc(), Initialization, asBackendZone() */ QTimeZone QTimeZone::systemTimeZone() { - return QTimeZone(global_tz->backend->systemTimeZoneId()); + // Use ID even if empty, as default constructor is invalid but empty-ID + // constructor goes to backend's default constructor, which may succeed. + const auto sys = QTimeZone(global_tz->backend->systemTimeZoneId()); + if (!sys.isValid()) { + static bool neverWarned = true; + if (neverWarned) { + // Racey but, at worst, merely repeats the warning. + neverWarned = false; + qWarning("Unable to determine system time zone: " + "please check your system configuration."); + } + } + return sys; } /*! diff --git a/tests/auto/corelib/time/qdate/tst_qdate.cpp b/tests/auto/corelib/time/qdate/tst_qdate.cpp index 7c1577c39a7..ab27af0dd81 100644 --- a/tests/auto/corelib/time/qdate/tst_qdate.cpp +++ b/tests/auto/corelib/time/qdate/tst_qdate.cpp @@ -573,6 +573,7 @@ void tst_QDate::startOfDay_endOfDay_data() #if QT_CONFIG(timezone) const QTimeZone sys = QTimeZone::systemTimeZone(); + QVERIFY2(sys.isValid(), "Test depends on properly configured system"); for (const auto &tran : transitions) { if (QTimeZone zone(tran.zone); zone.isValid()) { QTest::newRow(tran.test) @@ -728,7 +729,9 @@ void tst_QDate::startOfDay_endOfDay_bounds() QCOMPARE(qdteMin.startOfDay(UTC).date(), qdteMin); QCOMPARE(qdteMin.startOfDay().date(), qdteMin); #if QT_CONFIG(timezone) - QCOMPARE(qdteMin.startOfDay(QTimeZone::systemTimeZone()).date(), qdteMin); + const QTimeZone sys = QTimeZone::systemTimeZone(); + QVERIFY2(sys.isValid(), "Test depends on properly configured system"); + QCOMPARE(qdteMin.startOfDay(sys).date(), qdteMin); QTimeZone berlin("Europe/Berlin"); if (berlin.isValid()) QCOMPARE(qdteMin.startOfDay(berlin).date(), qdteMin); diff --git a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp index 7d60f5d0ff6..ff6f96c1a05 100644 --- a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp +++ b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp @@ -507,7 +507,9 @@ void tst_QTimeZone::asBackendZone() void tst_QTimeZone::systemZone() { const QTimeZone zone = QTimeZone::systemTimeZone(); - QVERIFY2(zone.isValid(), "Invalid system zone setting, tests are doomed."); + QVERIFY2(zone.isValid(), + "Invalid system zone setting, tests are doomed on misconfigured system."); + // This may fail on Windows if CLDR data doesn't map system MS ID to IANA ID: QCOMPARE(zone.id(), QTimeZone::systemTimeZoneId()); QCOMPARE(zone, QTimeZone(QTimeZone::systemTimeZoneId())); // Check it behaves the same as local-time: