summaryrefslogtreecommitdiffstats
path: root/src/corelib/time
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2020-08-28 15:32:09 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2020-09-28 15:55:47 +0000
commit87b07a60da183a60a7e7c79e5daa3ab69a03b4c3 (patch)
treeebff3c9cde2ed1cfcec5488afabbec13772670a9 /src/corelib/time
parent4d3939650dda199807f4707574ed39d871e340d8 (diff)
Don't guess UTC when we can't find a system zone name
If we're able to load a system zone without knowing its name, we shouldn't claim that its name is UTC. Instead, use the system zone information's name for the zone. Let the backend return an empty string if it can't determine the system zone ID, provided it has some way to get system zone info despite not knowing its name. This can happen on Windows if the system zone is one of Microsoft's idiosyncratic names that we don't recognize; or on Linux if /etc/timezone is a copy of a zoneinfo file, instead of a symlink. In support of that, handle empty ID as a request for system zone info, so that the backend constructors taking an IANA ID never get passed an empty ID; that gets routed to the default constructor instead. This incidentally restores QTzTimeZonePrivate's behavior, for empty ID, of reading the content of /etc/timezone if we are unable to determine the name of its zone any other way. Fixes: QTBUG-86306 Change-Id: Iad57c18199124f651ebc3d32c3deffca6eaab512 Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io> (cherry picked from commit b12d6c6a8ab5f7b01bdd2cb862a66a409700faa1) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/corelib/time')
-rw-r--r--src/corelib/time/qtimezone.cpp15
-rw-r--r--src/corelib/time/qtimezoneprivate_tz.cpp18
-rw-r--r--src/corelib/time/qtimezoneprivate_win.cpp8
3 files changed, 25 insertions, 16 deletions
diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp
index 87d8ea75f1..0309e43e52 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()) {
@@ -795,7 +796,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();
}
/*!
@@ -807,7 +816,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 c5c70b7364..b816b4ecff 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 0aaf469ed9..4209bc707b 100644
--- a/src/corelib/time/qtimezoneprivate_win.cpp
+++ b/src/corelib/time/qtimezoneprivate_win.cpp
@@ -642,6 +642,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();
}
}
@@ -864,12 +866,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;
}