Report as available every QTimeZone(qint32).id() result

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.6 6.5
Fixes: QTBUG-118586
Change-Id: Id9b378aee122ec841635584367022fcb47041fdd
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Edward Welbourne 2023-10-27 13:55:14 +02:00
parent 4e3518bf63
commit 4389b0c429
3 changed files with 13 additions and 2 deletions

View File

@ -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))
{
}
@ -1420,6 +1422,7 @@ bool QTimeZone::isTimeZoneIdAvailable(const QByteArray &ianaId)
return false;
#endif
return QUtcTimeZonePrivate().isTimeZoneIdAvailable(ianaId)
|| QUtcTimeZonePrivate::offsetFromUtcString(ianaId) != QTimeZonePrivate::invalidSeconds()
|| global_tz->backend->isTimeZoneIdAvailable(ianaId);
}

View File

@ -919,7 +919,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;
}

View File

@ -538,6 +538,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()