diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp index 74419e66c06..1895e9bf714 100644 --- a/src/corelib/time/qtimezoneprivate.cpp +++ b/src/corelib/time/qtimezoneprivate.cpp @@ -648,8 +648,12 @@ QByteArray QTimeZonePrivate::ianaIdToWindowsId(const QByteArray &id) QByteArray QTimeZonePrivate::windowsIdToDefaultIanaId(const QByteArray &windowsId) { for (const QWindowsData &data : windowsDataTable) { - if (data.windowsId() == windowsId) - return data.ianaId().toByteArray(); + if (data.windowsId() == windowsId) { + QByteArrayView id = data.ianaId(); + if (qsizetype cut = id.indexOf(' '); cut >= 0) + id = id.first(cut); + return id.toByteArray(); + } } return QByteArray(); } @@ -702,6 +706,17 @@ template<> QTimeZonePrivate *QSharedDataPointer::clone() return d->clone(); } +static bool isEntryInIanaList(QByteArrayView id, QByteArrayView ianaIds) +{ + qsizetype cut; + while ((cut = ianaIds.indexOf(' ')) >= 0) { + if (id == ianaIds.first(cut)) + return true; + ianaIds = ianaIds.sliced(cut); + } + return id == ianaIds; +} + /* UTC Offset implementation, used when QT_NO_SYSTEMLOCALE set and ICU is not being used, or for QDateTimes with a Qt:Spec of Qt::OffsetFromUtc. @@ -719,7 +734,7 @@ QUtcTimeZonePrivate::QUtcTimeZonePrivate(const QByteArray &id) { // Look for the name in the UTC list, if found set the values for (const QUtcData &data : utcDataTable) { - if (data.id() == id) { + if (isEntryInIanaList(id, data.id())) { QString name = QString::fromUtf8(id); init(id, data.offsetFromUtc, name, name, QLocale::AnyTerritory, name); break; @@ -869,7 +884,7 @@ bool QUtcTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const { // Only the zone IDs supplied by CLDR and recognized by constructor. for (const QUtcData &data : utcDataTable) { - if (data.id() == ianaId) + if (isEntryInIanaList(ianaId, data.id())) return true; } // But see offsetFromUtcString(), which lets us accept some "unavailable" IDs. @@ -881,8 +896,15 @@ QList QUtcTimeZonePrivate::availableTimeZoneIds() const // Only the zone IDs supplied by CLDR and recognized by constructor. QList result; result.reserve(std::size(utcDataTable)); - for (const QUtcData &data : utcDataTable) - result << data.id().toByteArray(); + for (const QUtcData &data : utcDataTable) { + QByteArrayView id = data.id(); + qsizetype cut; + while ((cut = id.indexOf(' ')) >= 0) { + result << id.first(cut).toByteArray(); + id = id.sliced(cut); + } + result << id.toByteArray(); + } // Not guaranteed to be sorted, so sort: std::sort(result.begin(), result.end()); // ### assuming no duplicates @@ -903,8 +925,15 @@ QList QUtcTimeZonePrivate::availableTimeZoneIds(qint32 offsetSeconds // and UTC-00:00 all have the same offset.) QList result; for (const QUtcData &data : utcDataTable) { - if (data.offsetFromUtc == offsetSeconds) - result << data.id().toByteArray(); + if (data.offsetFromUtc == offsetSeconds) { + QByteArrayView id = data.id(); + qsizetype cut; + while ((cut = id.indexOf(' ')) >= 0) { + result << id.first(cut).toByteArray(); + id = id.sliced(cut); + } + result << id.toByteArray(); + } } // Not guaranteed to be sorted, so sort: std::sort(result.begin(), result.end()); diff --git a/src/corelib/time/qtimezoneprivate_data_p.h b/src/corelib/time/qtimezoneprivate_data_p.h index 49d5be746ba..2bfa3c884bb 100644 --- a/src/corelib/time/qtimezoneprivate_data_p.h +++ b/src/corelib/time/qtimezoneprivate_data_p.h @@ -44,7 +44,7 @@ struct QZoneData quint16 windowsIdKey; // Windows ID Key quint16 territory; // Territory of IANA ID's, AnyTerritory means No Territory quint16 ianaIdIndex; // All IANA ID's for the Windows ID and Country, space separated - inline QLatin1StringView id() const; + inline QLatin1StringView id() const; // Space-joined list of IANA IDs inline auto ids() const { return id().tokenize(u' '); } }; @@ -52,17 +52,17 @@ struct QWindowsData { quint16 windowsIdKey; // Windows ID Key quint16 windowsIdIndex; // Windows ID Literal - quint16 ianaIdIndex; // Default IANA ID for the Windows ID + quint16 ianaIdIndex; // IANA IDs for the Windows ID qint32 offsetFromUtc; // Standard Time Offset from UTC, used for quick look-ups inline QByteArrayView windowsId() const; - inline QByteArrayView ianaId() const; + inline QByteArrayView ianaId() const; // Space-joined list of IANA IDs }; struct QUtcData { - quint16 ianaIdIndex; // IANA ID + quint16 ianaIdIndex; // IANA IDs qint32 offsetFromUtc; // Offset form UTC is seconds - inline QByteArrayView id() const; + inline QByteArrayView id() const; // Space-joined list of IANA IDs }; /* @@ -1234,6 +1234,7 @@ static constexpr char ianaIdData[] = { // GENERATED PART ENDS HERE inline QByteArrayView QWindowsData::windowsId() const { return windowsIdData + windowsIdIndex; } +// Each of the following returns a space-joined sequence of IANA IDs: inline QByteArrayView QWindowsData::ianaId() const { return ianaIdData + ianaIdIndex; } inline QByteArrayView QUtcData::id() const { return ianaIdData + ianaIdIndex; } inline QLatin1StringView QZoneData::id() const