From 575b9117f91db775354f08ddbeaf64689f9718f1 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 27 Oct 2023 13:55:14 +0200 Subject: [PATCH] Report as available every QTimeZone(qint32).id() result MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The QTimeZone(id) constructor accepts these IDs, but isTimeZoneIdAvailable() did not admit to this. Although we cannot sensibly list all 183,047 of them in availableTimeZoneIds(), we should not claim they are unavailable. The custom QTZ constructor needs to know when the ID it's been given is an IANA one (to refuse to use it), so it has to be able ask the backends for "is this IANA", so the UTC backend still has to report these IDs as invalid, leaving the QDT frontend to include the check for these offset zones. Extend isTimeZoneIdAvailable() test to include every offset-zone's ID within QTZ's recognized range of offsets. Although the actual range accepted by offsetFromUtcString() is wider, bounded by ±24:59:59, the constructor from offset seconds (rather than offset string) is bounded by ±16 hours. Pick-to: 6.5 Fixes: QTBUG-118586 Change-Id: Id9b378aee122ec841635584367022fcb47041fdd Reviewed-by: Thiago Macieira (cherry picked from commit 4389b0c42934b3a0abf9fcbef4f7c06b86ff1faa) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/time/qtimezone.cpp | 5 ++++- src/corelib/time/qtimezoneprivate.cpp | 4 +++- tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp | 6 ++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp index 2abf14c0458..6b6587e770c 100644 --- a/src/corelib/time/qtimezone.cpp +++ b/src/corelib/time/qtimezone.cpp @@ -532,7 +532,9 @@ QTimeZone::QTimeZone(int offsetSeconds) QTimeZone::QTimeZone(const QByteArray &zoneId, int offsetSeconds, const QString &name, const QString &abbreviation, QLocale::Territory territory, const QString &comment) - : d(isTimeZoneIdAvailable(zoneId) ? nullptr // Don't let client code hijack a real zone name. + : d(QUtcTimeZonePrivate().isTimeZoneIdAvailable(zoneId) + || global_tz->backend->isTimeZoneIdAvailable(zoneId) + ? nullptr // Don't let client code hijack a real zone name. : new QUtcTimeZonePrivate(zoneId, offsetSeconds, name, abbreviation, territory, comment)) { } @@ -1397,6 +1399,7 @@ bool QTimeZone::isTimeZoneIdAvailable(const QByteArray &ianaId) return false; #endif return QUtcTimeZonePrivate().isTimeZoneIdAvailable(ianaId) + || QUtcTimeZonePrivate::offsetFromUtcString(ianaId) != QTimeZonePrivate::invalidSeconds() || global_tz->backend->isTimeZoneIdAvailable(ianaId); } diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp index 6f0b51f8dd5..552e58f15b9 100644 --- a/src/corelib/time/qtimezoneprivate.cpp +++ b/src/corelib/time/qtimezoneprivate.cpp @@ -894,7 +894,9 @@ bool QUtcTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const if (isEntryInIanaList(ianaId, data.id())) return true; } - // But see offsetFromUtcString(), which lets us accept some "unavailable" IDs. + // Callers may want to || offsetFromUtcString(ianaId) != invalidSeconds(), + // but those are technically not IANA IDs and the custom QTimeZone + // constructor needs the return here to reflect that. return false; } diff --git a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp index 7d60f5d0ff6..ece22abee48 100644 --- a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp +++ b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp @@ -536,6 +536,12 @@ void tst_QTimeZone::isTimeZoneIdAvailable() QVERIFY2(QTimeZone::isTimeZoneIdAvailable(id), id); QVERIFY2(QTimeZone(id).isValid(), id); } + for (qint32 offset = QTimeZone::MinUtcOffsetSecs; + offset <= QTimeZone::MinUtcOffsetSecs; ++offset) { + const QByteArray id = QTimeZone(offset).id(); + QVERIFY2(QTimeZone::isTimeZoneIdAvailable(id), id); + QVERIFY2(QTimeZone(id).isValid(), id); + } } void tst_QTimeZone::utcOffsetId_data()