diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp index 45e37cb4031..e95700c64b8 100644 --- a/src/corelib/time/qtimezone.cpp +++ b/src/corelib/time/qtimezone.cpp @@ -79,6 +79,7 @@ static QTimeZonePrivate *newBackendTimeZone() // Create named time zone using appropriate backend static QTimeZonePrivate *newBackendTimeZone(const QByteArray &ianaId) { + Q_ASSERT(!ianaId.isEmpty()); #ifdef QT_NO_SYSTEMLOCALE #if QT_CONFIG(icu) return new QIcuTimeZonePrivate(ianaId); @@ -339,7 +340,7 @@ QTimeZone::QTimeZone(const QByteArray &ianaId) // If not a CLDR UTC offset ID then try creating it with the system backend. // Relies on backend not creating valid TZ with invalid name. if (!d->isValid()) - d = newBackendTimeZone(ianaId); + d = ianaId.isEmpty() ? newBackendTimeZone() : newBackendTimeZone(ianaId); // Can also handle UTC with arbitrary (valid) offset, but only do so as // fall-back, since either of the above may handle it more informatively. if (!d->isValid()) { @@ -767,7 +768,15 @@ QTimeZone::OffsetDataList QTimeZone::transitions(const QDateTime &fromDateTime, QByteArray QTimeZone::systemTimeZoneId() { - return global_tz->backend->systemTimeZoneId(); + const QByteArray sys = global_tz->backend->systemTimeZoneId(); + if (!sys.isEmpty()) + return sys; + // The system zone, despite the empty ID, may know its real ID anyway: + auto zone = systemTimeZone(); + if (zone.isValid() && !zone.id().isEmpty()) + return zone.id(); + // If all else fails, guess UTC. + return QTimeZonePrivate::utcQByteArray(); } /*! @@ -779,7 +788,7 @@ QByteArray QTimeZone::systemTimeZoneId() */ QTimeZone QTimeZone::systemTimeZone() { - return QTimeZone(QTimeZone::systemTimeZoneId()); + return QTimeZone(global_tz->backend->systemTimeZoneId()); } /*! diff --git a/src/corelib/time/qtimezoneprivate_tz.cpp b/src/corelib/time/qtimezoneprivate_tz.cpp index 0ac419ba5ad..4ac4559d368 100644 --- a/src/corelib/time/qtimezoneprivate_tz.cpp +++ b/src/corelib/time/qtimezoneprivate_tz.cpp @@ -641,7 +641,7 @@ QTzTimeZonePrivate::QTzTimeZonePrivate() // Create a named time zone QTzTimeZonePrivate::QTzTimeZonePrivate(const QByteArray &ianaId) { - init(ianaId.isEmpty() ? systemTimeZoneId() : ianaId); + init(ianaId); } QTzTimeZonePrivate::~QTzTimeZonePrivate() @@ -854,9 +854,6 @@ QTzTimeZoneCacheEntry QTzTimeZoneCache::fetchEntry(const QByteArray &ianaId) void QTzTimeZonePrivate::init(const QByteArray &ianaId) { - // System ID defaults to UTC, so is never empty; and our callers default to - // the system ID if what they're given is empty. - Q_ASSERT(!ianaId.isEmpty()); static QTzTimeZoneCache tzCache; const auto &entry = tzCache.fetchEntry(ianaId); if (entry.m_tranTimes.isEmpty() && entry.m_posixRule.isEmpty()) @@ -864,6 +861,15 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId) cached_data = std::move(entry); m_id = ianaId; + // Avoid empty ID, if we have an abbreviation to use instead + if (m_id.isEmpty()) { // We've read /etc/localtime's contents + for (const auto &abbr : cached_data.m_abbreviations) { + if (!abbr.isEmpty()) { + m_id = abbr; + break; + } + } + } } QLocale::Country QTzTimeZonePrivate::country() const @@ -1261,10 +1267,6 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const ianaId = reader.name(); } - // Give up for now and return UTC - if (ianaId.isEmpty()) - ianaId = utcQByteArray(); - return ianaId; } diff --git a/src/corelib/time/qtimezoneprivate_win.cpp b/src/corelib/time/qtimezoneprivate_win.cpp index 1dc362e45a8..7c80dbc38bb 100644 --- a/src/corelib/time/qtimezoneprivate_win.cpp +++ b/src/corelib/time/qtimezoneprivate_win.cpp @@ -510,6 +510,8 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId) m_id.clear(); m_windowsId.clear(); m_displayName.clear(); + } else if (m_id.isEmpty()) { + m_id = m_standardName.toUtf8(); } } @@ -732,12 +734,8 @@ QByteArray QWinTimeZonePrivate::systemTimeZoneId() const if (country != QLocale::AnyCountry) ianaId = windowsIdToDefaultIanaId(windowsId, country); // If we don't have a real country, or there wasn't a specific match, try the global default - if (ianaId.isEmpty()) { + if (ianaId.isEmpty()) ianaId = windowsIdToDefaultIanaId(windowsId); - // If no global default then probably an unknown Windows ID so return UTC - if (ianaId.isEmpty()) - return utcQByteArray(); - } return ianaId; }