summaryrefslogtreecommitdiffstats
path: root/src/corelib/time/qtimezoneprivate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/time/qtimezoneprivate.cpp')
-rw-r--r--src/corelib/time/qtimezoneprivate.cpp142
1 files changed, 125 insertions, 17 deletions
diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp
index 2ad0d874b6..b18b7e8758 100644
--- a/src/corelib/time/qtimezoneprivate.cpp
+++ b/src/corelib/time/qtimezoneprivate.cpp
@@ -5,6 +5,9 @@
#include "qtimezone.h"
#include "qtimezoneprivate_p.h"
+#if QT_CONFIG(timezone_locale)
+# include "qtimezonelocale_p.h"
+#endif
#include "qtimezoneprivate_data_p.h"
#include <qdatastream.h>
@@ -51,6 +54,11 @@ constexpr bool atLowerWindowsKey(const WindowsData &entry, qint16 winIdKey) noex
return entry.windowsIdKey < winIdKey;
}
+static bool earlierAliasId(const AliasData &entry, QByteArrayView aliasId) noexcept
+{
+ return entry.aliasId().compare(aliasId, Qt::CaseInsensitive) < 0;
+}
+
static bool earlierWindowsId(const WindowsData &entry, QByteArrayView winId) noexcept
{
return entry.windowsId().compare(winId, Qt::CaseInsensitive) < 0;
@@ -172,22 +180,37 @@ QString QTimeZonePrivate::displayName(qint64 atMSecsSinceEpoch,
QTimeZone::NameType nameType,
const QLocale &locale) const
{
- if (nameType == QTimeZone::OffsetName)
- return isoOffsetFormat(offsetFromUtc(atMSecsSinceEpoch));
-
- if (isDaylightTime(atMSecsSinceEpoch))
- return displayName(QTimeZone::DaylightTime, nameType, locale);
- else
- return displayName(QTimeZone::StandardTime, nameType, locale);
+ const Data tran = data(atMSecsSinceEpoch);
+ if (tran.atMSecsSinceEpoch != invalidMSecs()) {
+ if (nameType == QTimeZone::OffsetName && locale.language() == QLocale::C)
+ return isoOffsetFormat(tran.offsetFromUtc);
+ if (nameType == QTimeZone::ShortName && isDataLocale(locale))
+ return tran.abbreviation;
+
+ QTimeZone::TimeType timeType
+ = tran.daylightTimeOffset != 0 ? QTimeZone::DaylightTime : QTimeZone::StandardTime;
+#if QT_CONFIG(timezone_locale)
+ return localeName(atMSecsSinceEpoch, tran.offsetFromUtc, timeType, nameType, locale);
+#else
+ return displayName(timeType, nameType, locale);
+#endif
+ }
+ return QString();
}
QString QTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
QTimeZone::NameType nameType,
const QLocale &locale) const
{
- Q_UNUSED(timeType);
- Q_UNUSED(nameType);
- Q_UNUSED(locale);
+ const Data tran = data(timeType);
+ if (tran.atMSecsSinceEpoch != invalidMSecs()) {
+ if (nameType == QTimeZone::OffsetName && isDataLocale(locale))
+ return isoOffsetFormat(tran.offsetFromUtc);
+
+#if QT_CONFIG(timezone_locale)
+ return localeName(tran.atMSecsSinceEpoch, tran.offsetFromUtc, timeType, nameType, locale);
+#endif
+ }
return QString();
}
@@ -227,6 +250,56 @@ bool QTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
return false;
}
+QTimeZonePrivate::Data QTimeZonePrivate::data(QTimeZone::TimeType timeType) const
+{
+ // True if tran is valid and has the DST-ness to match timeType:
+ const auto validMatch = [timeType](const QTimeZonePrivate::Data &tran) {
+ return tran.atMSecsSinceEpoch != invalidMSecs()
+ && ((timeType == QTimeZone::DaylightTime) != (tran.daylightTimeOffset == 0));
+ };
+
+ // Get current tran, use if suitable:
+ const qint64 currentMSecs = QDateTime::currentMSecsSinceEpoch();
+ QTimeZonePrivate::Data tran = data(currentMSecs);
+ if (validMatch(tran))
+ return tran;
+
+ if (hasTransitions()) {
+ // Otherwise, next tran probably flips DST-ness:
+ tran = nextTransition(currentMSecs);
+ if (validMatch(tran))
+ return tran;
+
+ // Failing that, prev (or present, if current MSecs is exactly a
+ // transition moment) tran defines what data() got us and the one before
+ // that probably flips DST-ness; failing that, keep marching backwards
+ // in search of a DST interval:
+ tran = previousTransition(currentMSecs + 1);
+ while (tran.atMSecsSinceEpoch != invalidMSecs()) {
+ tran = previousTransition(tran.atMSecsSinceEpoch);
+ if (validMatch(tran))
+ return tran;
+ }
+ }
+ return {};
+}
+
+/*!
+ \internal
+
+ Returns true if the abbreviation given in data()'s returns is appropriate
+ for use in the given \a locale.
+
+ Base implementation assumes data() corresponds to the system locale; derived
+ classes should override if their data() is something else (such as
+ C/English).
+*/
+bool QTimeZonePrivate::isDataLocale(const QLocale &locale) const
+{
+ // Guess data is for the system locale unless backend overrides that.
+ return locale == QLocale::system();
+}
+
QTimeZonePrivate::Data QTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
{
Q_UNUSED(forMSecsSinceEpoch);
@@ -532,7 +605,8 @@ QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds() const
return QList<QByteArray>();
}
-static QList<QByteArray> selectAvailable(QList<QByteArray>&& desired, const QList<QByteArray>& all)
+static QList<QByteArray> selectAvailable(QList<QByteArrayView> &&desired,
+ const QList<QByteArray> &all)
{
std::sort(desired.begin(), desired.end());
const auto newEnd = std::unique(desired.begin(), desired.end());
@@ -547,13 +621,13 @@ static QList<QByteArray> selectAvailable(QList<QByteArray>&& desired, const QLis
QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds(QLocale::Territory territory) const
{
// Default fall-back mode, use the zoneTable to find Region of know Zones
- QList<QByteArray> regions;
+ QList<QByteArrayView> regions;
// First get all Zones in the Zones table belonging to the Region
for (const ZoneData &data : zoneDataTable) {
if (data.territory == territory) {
for (auto l1 : data.ids())
- regions << QByteArray(l1.data(), l1.size());
+ regions << QByteArrayView(l1.data(), l1.size());
}
}
return selectAvailable(std::move(regions), availableTimeZoneIds());
@@ -561,16 +635,16 @@ QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds(QLocale::Territory terr
QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds(int offsetFromUtc) const
{
- // Default fall-back mode, use the zoneTable to find Offset of know Zones
- QList<QByteArray> offsets;
- // First get all Zones in the table using the Offset
+ // Default fall-back mode: use the zoneTable to find offsets of know zones.
+ QList<QByteArrayView> offsets;
+ // First get all Zones in the table using the given offset:
for (const WindowsData &winData : windowsDataTable) {
if (winData.offsetFromUtc == offsetFromUtc) {
for (auto data = zoneStartForWindowsId(winData.windowsIdKey);
data != std::end(zoneDataTable) && data->windowsIdKey == winData.windowsIdKey;
++data) {
for (auto l1 : data->ids())
- offsets << QByteArray(l1.data(), l1.size());
+ offsets << QByteArrayView(l1.data(), l1.size());
}
}
}
@@ -701,6 +775,18 @@ QString QTimeZonePrivate::isoOffsetFormat(int offsetFromUtc, QTimeZone::NameType
return result;
}
+QByteArray QTimeZonePrivate::aliasToIana(QByteArrayView alias)
+{
+ const auto data = std::lower_bound(std::begin(aliasMappingTable), std::end(aliasMappingTable),
+ alias, earlierAliasId);
+ if (data != std::end(aliasMappingTable) && data->aliasId() == alias)
+ return data->ianaId().toByteArray();
+ // Note: empty return means not an alias, which is true of an ID that others
+ // are aliases to, as the table omits self-alias entries. Let caller sort
+ // that out, rather than allocating to return alias.toByteArray().
+ return {};
+}
+
QByteArray QTimeZonePrivate::ianaIdToWindowsId(const QByteArray &id)
{
const auto idUtf8 = QUtf8StringView(id);
@@ -906,6 +992,19 @@ QTimeZonePrivate::Data QUtcTimeZonePrivate::data(qint64 forMSecsSinceEpoch) cons
return d;
}
+// Override to shortcut past base's complications:
+QTimeZonePrivate::Data QUtcTimeZonePrivate::data(QTimeZone::TimeType timeType) const
+{
+ Q_UNUSED(timeType);
+ return data(QDateTime::currentMSecsSinceEpoch());
+}
+
+bool QUtcTimeZonePrivate::isDataLocale(const QLocale &locale) const
+{
+ // Officially only supports C locale names; these are surely also viable for English.
+ return locale.language() == QLocale::C || locale.language() == QLocale::English;
+}
+
void QUtcTimeZonePrivate::init(const QByteArray &zoneId)
{
m_id = zoneId;
@@ -933,6 +1032,15 @@ QString QUtcTimeZonePrivate::comment() const
return m_comment;
}
+// Override to bypass complications in base-class:
+QString QUtcTimeZonePrivate::displayName(qint64 atMSecsSinceEpoch,
+ QTimeZone::NameType nameType,
+ const QLocale &locale) const
+{
+ Q_UNUSED(atMSecsSinceEpoch);
+ return displayName(QTimeZone::StandardTime, nameType, locale);
+}
+
QString QUtcTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
QTimeZone::NameType nameType,
const QLocale &locale) const