summaryrefslogtreecommitdiffstats
path: root/src/corelib/time
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/time')
-rw-r--r--src/corelib/time/qdatetime.cpp16
-rw-r--r--src/corelib/time/qhijricalendar_data_p.h4
-rw-r--r--src/corelib/time/qjalalicalendar_data_p.h4
-rw-r--r--src/corelib/time/qromancalendar_data_p.h4
-rw-r--r--src/corelib/time/qtimezoneprivate_android.cpp2
-rw-r--r--src/corelib/time/qtimezoneprivate_data_p.h4
-rw-r--r--src/corelib/time/qtimezoneprivate_p.h16
-rw-r--r--src/corelib/time/qtimezoneprivate_tz.cpp182
8 files changed, 125 insertions, 107 deletions
diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp
index 47539141bd..5cd410c0b0 100644
--- a/src/corelib/time/qdatetime.cpp
+++ b/src/corelib/time/qdatetime.cpp
@@ -375,10 +375,11 @@ static int fromOffsetString(QStringView offsetString, bool *valid) noexcept
\reentrant
\brief The QDate class provides date functions.
-
- A QDate object represents a particular date. This can be expressed as a
- calendar date, i.e. year, month, and day numbers, in the proleptic Gregorian
- calendar.
+ A QDate object represents a particular day, regardless of calendar,
+ locale or other settings used when creating it or supplied by the system.
+ It can report the year, month and day of the month that represent the
+ day with respect to the proleptic Gregorian calendar or any calendar supplied
+ as a QCalendar object.
A QDate object is typically created by giving the year, month, and day
numbers explicitly. Note that QDate interprets year numbers less than 100 as
@@ -1676,9 +1677,8 @@ qint64 QDate::daysTo(QDate d) const
/*!
\fn bool QDate::operator==(QDate d) const
- Returns \c true if this date is equal to \a d; otherwise returns
- false.
-
+ Returns \c true if this date and \a d represent the same day, otherwise
+ \c false.
*/
/*!
@@ -1686,6 +1686,8 @@ qint64 QDate::daysTo(QDate d) const
Returns \c true if this date is different from \a d; otherwise
returns \c false.
+
+ \sa operator==()
*/
/*!
diff --git a/src/corelib/time/qhijricalendar_data_p.h b/src/corelib/time/qhijricalendar_data_p.h
index 2708db66be..5445375c3c 100644
--- a/src/corelib/time/qhijricalendar_data_p.h
+++ b/src/corelib/time/qhijricalendar_data_p.h
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
// GENERATED PART STARTS HERE
/*
- This part of the file was generated on 2020-01-30 from the
+ This part of the file was generated on 2020-04-07 from the
Common Locale Data Repository v36
http://www.unicode.org/cldr/
@@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE
*/
static const QCalendarLocale locale_data[] = {
- // lang script terr sLng long sSrt shrt sNrw naro Sizes...
+ // lang script terr sLong long sShrt short sNarw narow Sizes...
{ 1, 0, 0, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// C/AnyScript/AnyCountry
{ 3, 7, 69, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Oromo/Latin/Ethiopia
{ 3, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Oromo/Latin/Kenya
diff --git a/src/corelib/time/qjalalicalendar_data_p.h b/src/corelib/time/qjalalicalendar_data_p.h
index cc0d23da1f..c21c106e60 100644
--- a/src/corelib/time/qjalalicalendar_data_p.h
+++ b/src/corelib/time/qjalalicalendar_data_p.h
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
// GENERATED PART STARTS HERE
/*
- This part of the file was generated on 2020-01-30 from the
+ This part of the file was generated on 2020-04-07 from the
Common Locale Data Repository v36
http://www.unicode.org/cldr/
@@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE
*/
static const QCalendarLocale locale_data[] = {
- // lang script terr sLng long sSrt shrt sNrw naro Sizes...
+ // lang script terr sLong long sShrt short sNarw narow Sizes...
{ 1, 0, 0, 0, 0, 83, 83, 130, 153, 83, 83, 47, 47, 23, 26 },// C/AnyScript/AnyCountry
{ 3, 7, 69, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Oromo/Latin/Ethiopia
{ 3, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Oromo/Latin/Kenya
diff --git a/src/corelib/time/qromancalendar_data_p.h b/src/corelib/time/qromancalendar_data_p.h
index 94b8fe0d18..8a0ec14d49 100644
--- a/src/corelib/time/qromancalendar_data_p.h
+++ b/src/corelib/time/qromancalendar_data_p.h
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
// GENERATED PART STARTS HERE
/*
- This part of the file was generated on 2020-01-30 from the
+ This part of the file was generated on 2020-04-07 from the
Common Locale Data Repository v36
http://www.unicode.org/cldr/
@@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE
*/
static const QCalendarLocale locale_data[] = {
- // lang script terr sLng long sSrt shrt sNrw naro Sizes...
+ // lang script terr sLong long sShrt short sNarw narow Sizes...
{ 1, 0, 0, 0, 0, 85, 85, 132, 155, 85, 85, 47, 47, 23, 26 },// C/AnyScript/AnyCountry
{ 3, 7, 69, 181, 181, 291, 291, 132, 132,110,110, 47, 47, 23, 23 },// Oromo/Latin/Ethiopia
{ 3, 7, 111, 181, 181, 291, 291, 338, 132,110,110, 47, 47, 23, 23 },// Oromo/Latin/Kenya
diff --git a/src/corelib/time/qtimezoneprivate_android.cpp b/src/corelib/time/qtimezoneprivate_android.cpp
index 5cb8155dcc..fc3653752a 100644
--- a/src/corelib/time/qtimezoneprivate_android.cpp
+++ b/src/corelib/time/qtimezoneprivate_android.cpp
@@ -102,7 +102,7 @@ void QAndroidTimeZonePrivate::init(const QByteArray &ianaId)
for (int style = 1; m_id.isEmpty() && style-- > 0;) {
for (int dst = 1; m_id.isEmpty() && dst-- > 0;) {
m_id = match(androidTimeZone.callObjectMethod(
- "getDisplayName", "(ZI;)Ljava/lang/String;", bool(dst), style));
+ "getDisplayName", "(ZI)Ljava/lang/String;", bool(dst), style));
}
}
}
diff --git a/src/corelib/time/qtimezoneprivate_data_p.h b/src/corelib/time/qtimezoneprivate_data_p.h
index 822af9c703..6d2bbc83c1 100644
--- a/src/corelib/time/qtimezoneprivate_data_p.h
+++ b/src/corelib/time/qtimezoneprivate_data_p.h
@@ -115,8 +115,8 @@ struct QUtcData {
// GENERATED PART STARTS HERE
/*
- This part of the file was generated on 2019-10-24 from the
- Common Locale Data Repository v36 supplemental/windowsZones.xml file $Revision$
+ This part of the file was generated on 2020-02-28 from the
+ Common Locale Data Repository v36 file supplemental/windowsZones.xml
http://www.unicode.org/cldr/
diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h
index a57f61f381..f1b7fea1f9 100644
--- a/src/corelib/time/qtimezoneprivate_p.h
+++ b/src/corelib/time/qtimezoneprivate_p.h
@@ -290,6 +290,16 @@ Q_DECL_CONSTEXPR inline bool operator==(const QTzTransitionRule &lhs, const QTzT
Q_DECL_CONSTEXPR inline bool operator!=(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
{ return !operator==(lhs, rhs); }
+// These are stored separately from QTzTimeZonePrivate so that they can be
+// cached, avoiding the need to re-parse them from disk constantly.
+struct QTzTimeZoneCacheEntry
+{
+ QVector<QTzTransitionTime> m_tranTimes;
+ QVector<QTzTransitionRule> m_tranRules;
+ QList<QByteArray> m_abbreviations;
+ QByteArray m_posixRule;
+};
+
class Q_AUTOTEST_EXPORT QTzTimeZonePrivate final : public QTimeZonePrivate
{
QTzTimeZonePrivate(const QTzTimeZonePrivate &) = default;
@@ -337,13 +347,11 @@ private:
QVector<QTimeZonePrivate::Data> getPosixTransitions(qint64 msNear) const;
Data dataForTzTransition(QTzTransitionTime tran) const;
- QVector<QTzTransitionTime> m_tranTimes;
- QVector<QTzTransitionRule> m_tranRules;
- QList<QByteArray> m_abbreviations;
#if QT_CONFIG(icu)
mutable QSharedDataPointer<QTimeZonePrivate> m_icu;
#endif
- QByteArray m_posixRule;
+ QTzTimeZoneCacheEntry cached_data;
+ QVector<QTzTransitionTime> tranCache() const { return cached_data.m_tranTimes; }
};
#endif // Q_OS_UNIX
diff --git a/src/corelib/time/qtimezoneprivate_tz.cpp b/src/corelib/time/qtimezoneprivate_tz.cpp
index 5e55c6897d..01f9a6cce0 100644
--- a/src/corelib/time/qtimezoneprivate_tz.cpp
+++ b/src/corelib/time/qtimezoneprivate_tz.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2019 Crimson AS <info@crimson.no>
** Copyright (C) 2013 John Layt <jlayt@kde.org>
** Contact: https://www.qt.io/licensing/
**
@@ -42,6 +43,7 @@
#include "private/qlocale_tools_p.h"
#include <QtCore/QFile>
+#include <QtCore/QMutex>
#include <QtCore/QHash>
#include <QtCore/QDataStream>
#include <QtCore/QDateTime>
@@ -637,7 +639,7 @@ QTzTimeZonePrivate::QTzTimeZonePrivate()
// Create a named time zone
QTzTimeZonePrivate::QTzTimeZonePrivate(const QByteArray &ianaId)
{
- init(ianaId);
+ init(ianaId.isEmpty() ? systemTimeZoneId() : ianaId);
}
QTzTimeZonePrivate::~QTzTimeZonePrivate()
@@ -649,14 +651,26 @@ QTzTimeZonePrivate *QTzTimeZonePrivate::clone() const
return new QTzTimeZonePrivate(*this);
}
-void QTzTimeZonePrivate::init(const QByteArray &ianaId)
+class QTzTimeZoneCache
+{
+public:
+ QTzTimeZoneCacheEntry fetchEntry(const QByteArray &ianaId);
+
+private:
+ QTzTimeZoneCacheEntry findEntry(const QByteArray &ianaId);
+ QHash<QByteArray, QTzTimeZoneCacheEntry> m_cache;
+ QMutex m_mutex;
+};
+
+QTzTimeZoneCacheEntry QTzTimeZoneCache::findEntry(const QByteArray &ianaId)
{
+ QTzTimeZoneCacheEntry ret;
QFile tzif;
if (ianaId.isEmpty()) {
// Open system tz
tzif.setFileName(QStringLiteral("/etc/localtime"));
if (!tzif.open(QIODevice::ReadOnly))
- return;
+ return ret;
} else {
// Open named tz, try modern path first, if fails try legacy path
tzif.setFileName(QLatin1String("/usr/share/zoneinfo/") + QString::fromLocal8Bit(ianaId));
@@ -669,9 +683,9 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId)
if (PosixZone::parse(begin, zoneInfo.constEnd()).hasValidOffset()
&& (begin == zoneInfo.constEnd()
|| PosixZone::parse(begin, zoneInfo.constEnd()).hasValidOffset())) {
- m_id = m_posixRule = ianaId;
+ ret.m_posixRule = ianaId;
}
- return;
+ return ret;
}
}
}
@@ -682,59 +696,59 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId)
bool ok = false;
QTzHeader hdr = parseTzHeader(ds, &ok);
if (!ok || ds.status() != QDataStream::Ok)
- return;
+ return ret;
QVector<QTzTransition> tranList = parseTzTransitions(ds, hdr.tzh_timecnt, false);
if (ds.status() != QDataStream::Ok)
- return;
+ return ret;
QVector<QTzType> typeList = parseTzTypes(ds, hdr.tzh_typecnt);
if (ds.status() != QDataStream::Ok)
- return;
+ return ret;
QMap<int, QByteArray> abbrevMap = parseTzAbbreviations(ds, hdr.tzh_charcnt, typeList);
if (ds.status() != QDataStream::Ok)
- return;
+ return ret;
parseTzLeapSeconds(ds, hdr.tzh_leapcnt, false);
if (ds.status() != QDataStream::Ok)
- return;
+ return ret;
typeList = parseTzIndicators(ds, typeList, hdr.tzh_ttisstdcnt, hdr.tzh_ttisgmtcnt);
if (ds.status() != QDataStream::Ok)
- return;
+ return ret;
// If version 2 then parse the second block of data
if (hdr.tzh_version == '2' || hdr.tzh_version == '3') {
ok = false;
QTzHeader hdr2 = parseTzHeader(ds, &ok);
if (!ok || ds.status() != QDataStream::Ok)
- return;
+ return ret;
tranList = parseTzTransitions(ds, hdr2.tzh_timecnt, true);
if (ds.status() != QDataStream::Ok)
- return;
+ return ret;
typeList = parseTzTypes(ds, hdr2.tzh_typecnt);
if (ds.status() != QDataStream::Ok)
- return;
+ return ret;
abbrevMap = parseTzAbbreviations(ds, hdr2.tzh_charcnt, typeList);
if (ds.status() != QDataStream::Ok)
- return;
+ return ret;
parseTzLeapSeconds(ds, hdr2.tzh_leapcnt, true);
if (ds.status() != QDataStream::Ok)
- return;
+ return ret;
typeList = parseTzIndicators(ds, typeList, hdr2.tzh_ttisstdcnt, hdr2.tzh_ttisgmtcnt);
if (ds.status() != QDataStream::Ok)
- return;
- m_posixRule = parseTzPosixRule(ds);
+ return ret;
+ ret.m_posixRule = parseTzPosixRule(ds);
if (ds.status() != QDataStream::Ok)
- return;
+ return ret;
}
// Translate the TZ file into internal format
// Translate the array index based tz_abbrind into list index
const int size = abbrevMap.size();
- m_abbreviations.clear();
- m_abbreviations.reserve(size);
+ ret.m_abbreviations.clear();
+ ret.m_abbreviations.reserve(size);
QVector<int> abbrindList;
abbrindList.reserve(size);
for (auto it = abbrevMap.cbegin(), end = abbrevMap.cend(); it != end; ++it) {
- m_abbreviations.append(it.value());
+ ret.m_abbreviations.append(it.value());
abbrindList.append(it.key());
}
for (int i = 0; i < typeList.size(); ++i)
@@ -752,7 +766,7 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId)
// Now for each transition time calculate and store our rule:
const int tranCount = tranList.count();;
- m_tranTimes.reserve(tranCount);
+ ret.m_tranTimes.reserve(tranCount);
// The DST offset when in effect: usually stable, usually an hour:
int lastDstOff = 3600;
for (int i = 0; i < tranCount; i++) {
@@ -806,24 +820,48 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId)
rule.abbreviationIndex = tz_type.tz_abbrind;
// If the rule already exist then use that, otherwise add it
- int ruleIndex = m_tranRules.indexOf(rule);
+ int ruleIndex = ret.m_tranRules.indexOf(rule);
if (ruleIndex == -1) {
- m_tranRules.append(rule);
- tran.ruleIndex = m_tranRules.size() - 1;
+ ret.m_tranRules.append(rule);
+ tran.ruleIndex = ret.m_tranRules.size() - 1;
} else {
tran.ruleIndex = ruleIndex;
}
tran.atMSecsSinceEpoch = tz_tran.tz_time * 1000;
- m_tranTimes.append(tran);
+ ret.m_tranTimes.append(tran);
}
- if (m_tranTimes.isEmpty() && m_posixRule.isEmpty())
+
+ return ret;
+}
+
+QTzTimeZoneCacheEntry QTzTimeZoneCache::fetchEntry(const QByteArray &ianaId)
+{
+ QMutexLocker locker(&m_mutex);
+
+ // search the cache...
+ const auto& it = m_cache.find(ianaId);
+ if (it != m_cache.constEnd())
+ return *it;
+
+ // ... or build a new entry from scratch
+ QTzTimeZoneCacheEntry ret = findEntry(ianaId);
+ m_cache[ianaId] = ret;
+ return ret;
+}
+
+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())
return; // Invalid after all !
- if (ianaId.isEmpty())
- m_id = systemTimeZoneId();
- else
- m_id = ianaId;
+ cached_data = std::move(entry);
+ m_id = ianaId;
}
QLocale::Country QTzTimeZonePrivate::country() const
@@ -903,12 +941,12 @@ QString QTzTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
}
// Otherwise is strange sequence, so work backwards through trans looking for first match, if any
- auto it = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
+ auto it = std::partition_point(tranCache().cbegin(), tranCache().cend(),
[currentMSecs](const QTzTransitionTime &at) {
return at.atMSecsSinceEpoch <= currentMSecs;
});
- while (it != m_tranTimes.cbegin()) {
+ while (it != tranCache().cbegin()) {
--it;
tran = dataForTzTransition(*it);
int offset = tran.daylightTimeOffset;
@@ -944,7 +982,7 @@ int QTzTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
bool QTzTimeZonePrivate::hasDaylightTime() const
{
// TODO Perhaps cache as frequently accessed?
- for (const QTzTransitionRule &rule : m_tranRules) {
+ for (const QTzTransitionRule &rule : cached_data.m_tranRules) {
if (rule.dstOffset != 0)
return true;
}
@@ -960,11 +998,11 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::dataForTzTransition(QTzTransitionTime
{
QTimeZonePrivate::Data data;
data.atMSecsSinceEpoch = tran.atMSecsSinceEpoch;
- QTzTransitionRule rule = m_tranRules.at(tran.ruleIndex);
+ QTzTransitionRule rule = cached_data.m_tranRules.at(tran.ruleIndex);
data.standardTimeOffset = rule.stdOffset;
data.daylightTimeOffset = rule.dstOffset;
data.offsetFromUtc = rule.stdOffset + rule.dstOffset;
- data.abbreviation = QString::fromUtf8(m_abbreviations.at(rule.abbreviationIndex));
+ data.abbreviation = QString::fromUtf8(cached_data.m_abbreviations.at(rule.abbreviationIndex));
return data;
}
@@ -972,37 +1010,37 @@ QVector<QTimeZonePrivate::Data> QTzTimeZonePrivate::getPosixTransitions(qint64 m
{
const int year = QDateTime::fromMSecsSinceEpoch(msNear, Qt::UTC).date().year();
// The Data::atMSecsSinceEpoch of the single entry if zone is constant:
- qint64 atTime = m_tranTimes.isEmpty() ? msNear : m_tranTimes.last().atMSecsSinceEpoch;
- return calculatePosixTransitions(m_posixRule, year - 1, year + 1, atTime);
+ qint64 atTime = tranCache().isEmpty() ? msNear : tranCache().last().atMSecsSinceEpoch;
+ return calculatePosixTransitions(cached_data.m_posixRule, year - 1, year + 1, atTime);
}
QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
{
// If the required time is after the last transition (or there were none)
// and we have a POSIX rule, then use it:
- if (!m_posixRule.isEmpty()
- && (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch)) {
+ if (!cached_data.m_posixRule.isEmpty()
+ && (tranCache().isEmpty() || tranCache().last().atMSecsSinceEpoch < forMSecsSinceEpoch)) {
QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(forMSecsSinceEpoch);
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
[forMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
});
// Use most recent, if any in the past; or the first if we have no other rules:
- if (it > posixTrans.cbegin() || (m_tranTimes.isEmpty() && it < posixTrans.cend())) {
+ if (it > posixTrans.cbegin() || (tranCache().isEmpty() && it < posixTrans.cend())) {
QTimeZonePrivate::Data data = *(it > posixTrans.cbegin() ? it - 1 : it);
data.atMSecsSinceEpoch = forMSecsSinceEpoch;
return data;
}
}
- if (m_tranTimes.isEmpty()) // Only possible if !isValid()
+ if (tranCache().isEmpty()) // Only possible if !isValid()
return invalidData();
// Otherwise, use the rule for the most recent or first transition:
- auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
+ auto last = std::partition_point(tranCache().cbegin(), tranCache().cend(),
[forMSecsSinceEpoch] (const QTzTransitionTime &at) {
return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
});
- if (last > m_tranTimes.cbegin())
+ if (last > tranCache().cbegin())
--last;
Data data = dataForTzTransition(*last);
data.atMSecsSinceEpoch = forMSecsSinceEpoch;
@@ -1018,8 +1056,8 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSince
{
// If the required time is after the last transition (or there were none)
// and we have a POSIX rule, then use it:
- if (!m_posixRule.isEmpty()
- && (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < afterMSecsSinceEpoch)) {
+ if (!cached_data.m_posixRule.isEmpty()
+ && (tranCache().isEmpty() || tranCache().last().atMSecsSinceEpoch < afterMSecsSinceEpoch)) {
QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(afterMSecsSinceEpoch);
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
[afterMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
@@ -1030,19 +1068,19 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSince
}
// Otherwise, if we can find a valid tran, use its rule:
- auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
+ auto last = std::partition_point(tranCache().cbegin(), tranCache().cend(),
[afterMSecsSinceEpoch] (const QTzTransitionTime &at) {
return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch;
});
- return last != m_tranTimes.cend() ? dataForTzTransition(*last) : invalidData();
+ return last != tranCache().cend() ? dataForTzTransition(*last) : invalidData();
}
QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
{
// If the required time is after the last transition (or there were none)
// and we have a POSIX rule, then use it:
- if (!m_posixRule.isEmpty()
- && (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < beforeMSecsSinceEpoch)) {
+ if (!cached_data.m_posixRule.isEmpty()
+ && (tranCache().isEmpty() || tranCache().last().atMSecsSinceEpoch < beforeMSecsSinceEpoch)) {
QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(beforeMSecsSinceEpoch);
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
[beforeMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
@@ -1051,15 +1089,15 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecs
if (it > posixTrans.cbegin())
return *--it;
// It fell between the last transition (if any) and the first of the POSIX rule:
- return m_tranTimes.isEmpty() ? invalidData() : dataForTzTransition(m_tranTimes.last());
+ return tranCache().isEmpty() ? invalidData() : dataForTzTransition(tranCache().last());
}
// Otherwise if we can find a valid tran then use its rule
- auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
+ auto last = std::partition_point(tranCache().cbegin(), tranCache().cend(),
[beforeMSecsSinceEpoch] (const QTzTransitionTime &at) {
return at.atMSecsSinceEpoch < beforeMSecsSinceEpoch;
});
- return last > m_tranTimes.cbegin() ? dataForTzTransition(*--last) : invalidData();
+ return last > tranCache().cbegin() ? dataForTzTransition(*--last) : invalidData();
}
static long getSymloopMax()
@@ -1088,15 +1126,15 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const
{
// Check TZ env var first, if not populated try find it
QByteArray ianaId = qgetenv("TZ");
- if (!ianaId.isEmpty() && ianaId.at(0) == ':')
- ianaId = ianaId.mid(1);
// The TZ value can be ":/etc/localtime" which libc considers
// to be a "default timezone", in which case it will be read
// by one of the blocks below, so unset it here so it is not
// considered as a valid/found ianaId
- if (ianaId == "/etc/localtime")
+ if (ianaId == ":/etc/localtime")
ianaId.clear();
+ else if (ianaId.startsWith(':'))
+ ianaId = ianaId.mid(1);
// On most distros /etc/localtime is a symlink to a real file so extract name from the path
if (ianaId.isEmpty()) {
@@ -1115,36 +1153,6 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const
}
}
- // On Debian Etch up to Jessie, /etc/localtime is a regular file while the actual name is in /etc/timezone
- if (ianaId.isEmpty()) {
- QFile tzif(QStringLiteral("/etc/timezone"));
- if (tzif.open(QIODevice::ReadOnly)) {
- // TODO QTextStream inefficient, replace later
- QTextStream ts(&tzif);
- if (!ts.atEnd())
- ianaId = ts.readLine().toUtf8();
- }
- }
-
- // On some Red Hat distros /etc/localtime is real file with name held in /etc/sysconfig/clock
- // in a line like ZONE="Europe/Oslo" or TIMEZONE="Europe/Oslo"
- if (ianaId.isEmpty()) {
- QFile tzif(QStringLiteral("/etc/sysconfig/clock"));
- if (tzif.open(QIODevice::ReadOnly)) {
- // TODO QTextStream inefficient, replace later
- QTextStream ts(&tzif);
- QString line;
- while (ianaId.isEmpty() && !ts.atEnd() && ts.status() == QTextStream::Ok) {
- line = ts.readLine();
- if (line.startsWith(QLatin1String("ZONE="))) {
- ianaId = line.midRef(6, line.size() - 7).toUtf8();
- } else if (line.startsWith(QLatin1String("TIMEZONE="))) {
- ianaId = line.midRef(10, line.size() - 11).toUtf8();
- }
- }
- }
- }
-
// Some systems (e.g. uClibc) have a default value for $TZ in /etc/TZ:
if (ianaId.isEmpty()) {
QFile zone(QStringLiteral("/etc/TZ"));