Use std::partition_point for faster searches among transitions
QTzTimeZonePrivate's methods were iterating transitions from first to last, or last to first, to find where .atMSecsSinceEpoch crossed some threshold; but the transitions are sorted in order of increasing .atMSecsSinceEpoch, so binary chop would be more efficient than such linear searches. So use std::partition_point() instead. Change-Id: I65c43cb20fca6685a22ea52a4ca2f1089c128ebf Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
98b030fc95
commit
1acafb1207
@ -878,14 +878,17 @@ QString QTzTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise is strange sequence, so work backwards through trans looking for first match, if any
|
// Otherwise is strange sequence, so work backwards through trans looking for first match, if any
|
||||||
for (int i = m_tranTimes.size() - 1; i >= 0; --i) {
|
auto it = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
|
||||||
if (m_tranTimes.at(i).atMSecsSinceEpoch <= currentMSecs) {
|
[currentMSecs](const QTzTransitionTime &at) {
|
||||||
tran = dataForTzTransition(m_tranTimes.at(i));
|
return at.atMSecsSinceEpoch <= currentMSecs;
|
||||||
if ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0)
|
});
|
||||||
|| (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0)) {
|
|
||||||
return tran.abbreviation;
|
while (it != m_tranTimes.cbegin()) {
|
||||||
}
|
--it;
|
||||||
}
|
tran = dataForTzTransition(*it);
|
||||||
|
int offset = tran.daylightTimeOffset;
|
||||||
|
if ((timeType == QTimeZone::DaylightTime) != (offset == 0))
|
||||||
|
return tran.abbreviation;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise if no match use current data
|
// Otherwise if no match use current data
|
||||||
@ -900,7 +903,7 @@ QString QTzTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
|
|||||||
int QTzTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
|
int QTzTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
|
||||||
{
|
{
|
||||||
const QTimeZonePrivate::Data tran = data(atMSecsSinceEpoch);
|
const QTimeZonePrivate::Data tran = data(atMSecsSinceEpoch);
|
||||||
return tran.standardTimeOffset + tran.daylightTimeOffset;
|
return tran.offsetFromUtc; // == tran.standardTimeOffset + tran.daylightTimeOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
int QTzTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
|
int QTzTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
|
||||||
@ -942,40 +945,38 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::dataForTzTransition(QTzTransitionTime
|
|||||||
|
|
||||||
QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
|
QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
|
||||||
{
|
{
|
||||||
|
// If we have no rules (so probably an invalid tz), return invalid data:
|
||||||
|
if (!m_tranTimes.size())
|
||||||
|
return invalidData();
|
||||||
|
|
||||||
// If the required time is after the last transition and we have a POSIX rule then use it
|
// If the required time is after the last transition and we have a POSIX rule then use it
|
||||||
if (m_tranTimes.size() > 0 && m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch
|
if (m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch
|
||||||
&& !m_posixRule.isEmpty() && forMSecsSinceEpoch >= 0) {
|
&& !m_posixRule.isEmpty() && forMSecsSinceEpoch >= 0) {
|
||||||
const int year = QDateTime::fromMSecsSinceEpoch(forMSecsSinceEpoch, Qt::UTC).date().year();
|
const int year = QDateTime::fromMSecsSinceEpoch(forMSecsSinceEpoch, Qt::UTC).date().year();
|
||||||
QVector<QTimeZonePrivate::Data> posixTrans =
|
QVector<QTimeZonePrivate::Data> posixTrans =
|
||||||
calculatePosixTransitions(m_posixRule, year - 1, year + 1,
|
calculatePosixTransitions(m_posixRule, year - 1, year + 1,
|
||||||
m_tranTimes.last().atMSecsSinceEpoch);
|
m_tranTimes.last().atMSecsSinceEpoch);
|
||||||
for (int i = posixTrans.size() - 1; i >= 0; --i) {
|
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
|
||||||
if (posixTrans.at(i).atMSecsSinceEpoch <= forMSecsSinceEpoch) {
|
[forMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
|
||||||
QTimeZonePrivate::Data data = posixTrans.at(i);
|
return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
|
||||||
data.atMSecsSinceEpoch = forMSecsSinceEpoch;
|
});
|
||||||
return data;
|
if (it > posixTrans.cbegin()) {
|
||||||
}
|
QTimeZonePrivate::Data data = *--it;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise if we can find a valid tran then use its rule
|
|
||||||
for (int i = m_tranTimes.size() - 1; i >= 0; --i) {
|
|
||||||
if (m_tranTimes.at(i).atMSecsSinceEpoch <= forMSecsSinceEpoch) {
|
|
||||||
Data data = dataForTzTransition(m_tranTimes.at(i));
|
|
||||||
data.atMSecsSinceEpoch = forMSecsSinceEpoch;
|
data.atMSecsSinceEpoch = forMSecsSinceEpoch;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise use the earliest transition we have
|
// Otherwise, if we can find a valid tran, then use its rule:
|
||||||
if (m_tranTimes.size() > 0) {
|
auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
|
||||||
Data data = dataForTzTransition(m_tranTimes.at(0));
|
[forMSecsSinceEpoch] (const QTzTransitionTime &at) {
|
||||||
data.atMSecsSinceEpoch = forMSecsSinceEpoch;
|
return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
|
||||||
return data;
|
});
|
||||||
}
|
if (last > m_tranTimes.cbegin())
|
||||||
|
--last;
|
||||||
// Otherwise we have no rules, so probably an invalid tz, so return invalid data
|
Data data = dataForTzTransition(*last);
|
||||||
return invalidData();
|
data.atMSecsSinceEpoch = forMSecsSinceEpoch;
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QTzTimeZonePrivate::hasTransitions() const
|
bool QTzTimeZonePrivate::hasTransitions() const
|
||||||
@ -992,21 +993,20 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSince
|
|||||||
QVector<QTimeZonePrivate::Data> posixTrans =
|
QVector<QTimeZonePrivate::Data> posixTrans =
|
||||||
calculatePosixTransitions(m_posixRule, year - 1, year + 1,
|
calculatePosixTransitions(m_posixRule, year - 1, year + 1,
|
||||||
m_tranTimes.last().atMSecsSinceEpoch);
|
m_tranTimes.last().atMSecsSinceEpoch);
|
||||||
for (int i = 0; i < posixTrans.size(); ++i) {
|
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
|
||||||
if (posixTrans.at(i).atMSecsSinceEpoch > afterMSecsSinceEpoch)
|
[afterMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
|
||||||
return posixTrans.at(i);
|
return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch;
|
||||||
}
|
});
|
||||||
|
|
||||||
|
return it == posixTrans.cend() ? invalidData() : *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise if we can find a valid tran then use its rule
|
// Otherwise, if we can find a valid tran, use its rule:
|
||||||
for (int i = 0; i < m_tranTimes.size(); ++i) {
|
auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
|
||||||
if (m_tranTimes.at(i).atMSecsSinceEpoch > afterMSecsSinceEpoch) {
|
[afterMSecsSinceEpoch] (const QTzTransitionTime &at) {
|
||||||
return dataForTzTransition(m_tranTimes.at(i));
|
return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch;
|
||||||
}
|
});
|
||||||
}
|
return last != m_tranTimes.cend() ? dataForTzTransition(*last) : invalidData();
|
||||||
|
|
||||||
// Otherwise we have no rule, or there is no next transition, so return invalid data
|
|
||||||
return invalidData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
|
QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
|
||||||
@ -1018,21 +1018,20 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecs
|
|||||||
QVector<QTimeZonePrivate::Data> posixTrans =
|
QVector<QTimeZonePrivate::Data> posixTrans =
|
||||||
calculatePosixTransitions(m_posixRule, year - 1, year + 1,
|
calculatePosixTransitions(m_posixRule, year - 1, year + 1,
|
||||||
m_tranTimes.last().atMSecsSinceEpoch);
|
m_tranTimes.last().atMSecsSinceEpoch);
|
||||||
for (int i = posixTrans.size() - 1; i >= 0; --i) {
|
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
|
||||||
if (posixTrans.at(i).atMSecsSinceEpoch < beforeMSecsSinceEpoch)
|
[beforeMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
|
||||||
return posixTrans.at(i);
|
return at.atMSecsSinceEpoch < beforeMSecsSinceEpoch;
|
||||||
}
|
});
|
||||||
|
Q_ASSERT(it > posixTrans.cbegin());
|
||||||
|
return *--it;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise if we can find a valid tran then use its rule
|
// Otherwise if we can find a valid tran then use its rule
|
||||||
for (int i = m_tranTimes.size() - 1; i >= 0; --i) {
|
auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
|
||||||
if (m_tranTimes.at(i).atMSecsSinceEpoch < beforeMSecsSinceEpoch) {
|
[beforeMSecsSinceEpoch] (const QTzTransitionTime &at) {
|
||||||
return dataForTzTransition(m_tranTimes.at(i));
|
return at.atMSecsSinceEpoch < beforeMSecsSinceEpoch;
|
||||||
}
|
});
|
||||||
}
|
return last > m_tranTimes.cbegin() ? dataForTzTransition(*--last) : invalidData();
|
||||||
|
|
||||||
// Otherwise we have no rule, so return invalid data
|
|
||||||
return invalidData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Could cache the value and monitor the required files for any changes
|
// TODO Could cache the value and monitor the required files for any changes
|
||||||
|
Loading…
x
Reference in New Issue
Block a user