Make QTimeZonePrivate::Data construction easier
Turn QTZP::invalidData() into a default constructor. A second constructor taking needed details avoids exercising that default constructor elsewhere, when the invalid values aren't what we need. All constructed instances now have all members initialized. In the TZ backend, add some PosixZone helpers to create Data objects, reducing the complexity of calculatePosixTransitions(). Task-number: QTBUG-122619 Change-Id: I56557a2f6249d60012355d5d72c662474be76e51 Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>bb10
parent
7aada633be
commit
fccf6cfdd2
|
|
@ -230,7 +230,7 @@ bool QTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
|
|||
QTimeZonePrivate::Data QTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
|
||||
{
|
||||
Q_UNUSED(forMSecsSinceEpoch);
|
||||
return invalidData();
|
||||
return {};
|
||||
}
|
||||
|
||||
// Private only method for use by QDateTime to convert local msecs to epoch msecs
|
||||
|
|
@ -489,13 +489,13 @@ bool QTimeZonePrivate::hasTransitions() const
|
|||
QTimeZonePrivate::Data QTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
|
||||
{
|
||||
Q_UNUSED(afterMSecsSinceEpoch);
|
||||
return invalidData();
|
||||
return {};
|
||||
}
|
||||
|
||||
QTimeZonePrivate::Data QTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
|
||||
{
|
||||
Q_UNUSED(beforeMSecsSinceEpoch);
|
||||
return invalidData();
|
||||
return {};
|
||||
}
|
||||
|
||||
QTimeZonePrivate::DataList QTimeZonePrivate::transitions(qint64 fromMSecsSinceEpoch,
|
||||
|
|
@ -586,16 +586,6 @@ void QTimeZonePrivate::serialize(QDataStream &ds) const
|
|||
|
||||
// Static Utility Methods
|
||||
|
||||
QTimeZonePrivate::Data QTimeZonePrivate::invalidData()
|
||||
{
|
||||
Data data;
|
||||
data.atMSecsSinceEpoch = invalidMSecs();
|
||||
data.offsetFromUtc = invalidSeconds();
|
||||
data.standardTimeOffset = invalidSeconds();
|
||||
data.daylightTimeOffset = invalidSeconds();
|
||||
return data;
|
||||
}
|
||||
|
||||
QTimeZone::OffsetData QTimeZonePrivate::invalidOffsetData()
|
||||
{
|
||||
QTimeZone::OffsetData offsetData;
|
||||
|
|
|
|||
|
|
@ -182,16 +182,11 @@ bool QAndroidTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
|
|||
QTimeZonePrivate::Data QAndroidTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
|
||||
{
|
||||
if (androidTimeZone.isValid()) {
|
||||
Data data;
|
||||
data.atMSecsSinceEpoch = forMSecsSinceEpoch;
|
||||
data.standardTimeOffset = standardTimeOffset(forMSecsSinceEpoch);
|
||||
data.offsetFromUtc = offsetFromUtc(forMSecsSinceEpoch);
|
||||
data.daylightTimeOffset = data.offsetFromUtc - data.standardTimeOffset;
|
||||
data.abbreviation = abbreviation(forMSecsSinceEpoch);
|
||||
return data;
|
||||
} else {
|
||||
return invalidData();
|
||||
return Data(abbreviation(forMSecsSinceEpoch), forMSecsSinceEpoch,
|
||||
offsetFromUtc(forMSecsSinceEpoch),
|
||||
standardTimeOffset(forMSecsSinceEpoch));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// java.util.TimeZone does not directly provide transitions,
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ static QTimeZonePrivate::Data ucalTimeZoneTransition(UCalendar *m_ucal,
|
|||
UTimeZoneTransitionType type,
|
||||
qint64 atMSecsSinceEpoch)
|
||||
{
|
||||
QTimeZonePrivate::Data tran = QTimeZonePrivate::invalidData();
|
||||
QTimeZonePrivate::Data tran;
|
||||
|
||||
// Clone the ucal so we don't change the shared object
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
|
@ -384,7 +384,7 @@ bool QIcuTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
|
|||
QTimeZonePrivate::Data QIcuTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
|
||||
{
|
||||
// Available in ICU C++ api, and draft C api in v50
|
||||
QTimeZonePrivate::Data data = invalidData();
|
||||
QTimeZonePrivate::Data data;
|
||||
#if U_ICU_VERSION_MAJOR_NUM >= 50
|
||||
data = ucalTimeZoneTransition(m_ucal, UCAL_TZ_TRANSITION_PREVIOUS_INCLUSIVE,
|
||||
forMSecsSinceEpoch);
|
||||
|
|
@ -417,7 +417,7 @@ QTimeZonePrivate::Data QIcuTimeZonePrivate::nextTransition(qint64 afterMSecsSinc
|
|||
return ucalTimeZoneTransition(m_ucal, UCAL_TZ_TRANSITION_NEXT, afterMSecsSinceEpoch);
|
||||
#else
|
||||
Q_UNUSED(afterMSecsSinceEpoch);
|
||||
return invalidData();
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -428,7 +428,7 @@ QTimeZonePrivate::Data QIcuTimeZonePrivate::previousTransition(qint64 beforeMSec
|
|||
return ucalTimeZoneTransition(m_ucal, UCAL_TZ_TRANSITION_PREVIOUS, beforeMSecsSinceEpoch);
|
||||
#else
|
||||
Q_UNUSED(beforeMSecsSinceEpoch);
|
||||
return invalidData();
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::nextTransition(qint64 afterMSecsSinc
|
|||
const NSTimeInterval nextSecs = nextDate.timeIntervalSince1970;
|
||||
if (nextDate == nil || nextSecs <= seconds) {
|
||||
[nextDate release];
|
||||
return invalidData();
|
||||
return {};
|
||||
}
|
||||
tran.atMSecsSinceEpoch = nextSecs * 1000;
|
||||
tran.offsetFromUtc = [m_nstz secondsFromGMTForDate:nextDate];
|
||||
|
|
@ -273,7 +273,7 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::previousTransition(qint64 beforeMSec
|
|||
return data(qint64(prevSecs * 1e3));
|
||||
|
||||
// No transition data; or first transition later than requested time.
|
||||
return invalidData();
|
||||
return {};
|
||||
}
|
||||
|
||||
QByteArray QMacTimeZonePrivate::systemTimeZoneId() const
|
||||
|
|
|
|||
|
|
@ -44,13 +44,26 @@ QT_BEGIN_NAMESPACE
|
|||
class Q_AUTOTEST_EXPORT QTimeZonePrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
//Version of QTimeZone::OffsetData struct using msecs for efficiency
|
||||
// Version of QTimeZone::OffsetData struct using msecs for efficiency
|
||||
struct Data {
|
||||
QString abbreviation;
|
||||
qint64 atMSecsSinceEpoch;
|
||||
int offsetFromUtc;
|
||||
int standardTimeOffset;
|
||||
int daylightTimeOffset;
|
||||
Data()
|
||||
: atMSecsSinceEpoch(QTimeZonePrivate::invalidMSecs()),
|
||||
offsetFromUtc(QTimeZonePrivate::invalidSeconds()),
|
||||
standardTimeOffset(QTimeZonePrivate::invalidSeconds()),
|
||||
daylightTimeOffset(QTimeZonePrivate::invalidSeconds())
|
||||
{}
|
||||
Data(const QString &name, qint64 when, int offset, int standard)
|
||||
: abbreviation(name),
|
||||
atMSecsSinceEpoch(when),
|
||||
offsetFromUtc(offset),
|
||||
standardTimeOffset(standard),
|
||||
daylightTimeOffset(offset - standard)
|
||||
{}
|
||||
};
|
||||
typedef QList<Data> DataList;
|
||||
|
||||
|
|
@ -112,7 +125,6 @@ public:
|
|||
{ return (std::numeric_limits<qint64>::min)(); }
|
||||
[[nodiscard]] static constexpr qint64 invalidSeconds()
|
||||
{ return (std::numeric_limits<int>::min)(); }
|
||||
static Data invalidData();
|
||||
static QTimeZone::OffsetData invalidOffsetData();
|
||||
static QTimeZone::OffsetData toOffsetData(const Data &data);
|
||||
static bool isValidId(const QByteArray &ianaId);
|
||||
|
|
|
|||
|
|
@ -523,6 +523,16 @@ struct PosixZone
|
|||
QString name;
|
||||
int offset = InvalidOffset;
|
||||
bool hasValidOffset() const noexcept { return offset != InvalidOffset; }
|
||||
QTimeZonePrivate::Data dataAt(qint64 when)
|
||||
{
|
||||
Q_ASSERT(hasValidOffset());
|
||||
return QTimeZonePrivate::Data(name, when, offset, offset);
|
||||
}
|
||||
QTimeZonePrivate::Data dataAtOffset(qint64 when, int standard)
|
||||
{
|
||||
Q_ASSERT(hasValidOffset());
|
||||
return QTimeZonePrivate::Data(name, when, offset, standard);
|
||||
}
|
||||
|
||||
static PosixZone parse(const char *&pos, const char *end);
|
||||
};
|
||||
|
|
@ -663,13 +673,9 @@ static QList<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray
|
|||
|
||||
// If only the name part, or no DST specified, then no transitions
|
||||
if (parts.size() == 1 || !dstZone.hasValidOffset()) {
|
||||
QTimeZonePrivate::Data data;
|
||||
data.atMSecsSinceEpoch = lastTranMSecs;
|
||||
data.offsetFromUtc = stdZone.offset;
|
||||
data.standardTimeOffset = stdZone.offset;
|
||||
data.daylightTimeOffset = 0;
|
||||
data.abbreviation = stdZone.name.isEmpty() ? QString::fromUtf8(parts.at(0)) : stdZone.name;
|
||||
result << data;
|
||||
result.emplaceBack(
|
||||
stdZone.name.isEmpty() ? QString::fromUtf8(parts.at(0)) : stdZone.name,
|
||||
lastTranMSecs, stdZone.offset, stdZone.offset);
|
||||
return result;
|
||||
}
|
||||
if (parts.size() < 3 || parts.at(1).isEmpty() || parts.at(2).isEmpty())
|
||||
|
|
@ -702,40 +708,33 @@ static QList<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray
|
|||
// moments; the atMSecsSinceEpoch values computed from them are
|
||||
// correctly offse to be UTC-based.
|
||||
|
||||
QTimeZonePrivate::Data dstData; // Transition to DST
|
||||
// Transition to daylight-saving time:
|
||||
QDateTime dst(calculatePosixDate(dstDateRule, year)
|
||||
.startOfDay(QTimeZone::UTC).addSecs(dstTime));
|
||||
dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - stdZone.offset * 1000;
|
||||
dstData.offsetFromUtc = dstZone.offset;
|
||||
dstData.standardTimeOffset = stdZone.offset;
|
||||
dstData.daylightTimeOffset = dstZone.offset - stdZone.offset;
|
||||
dstData.abbreviation = dstZone.name;
|
||||
QTimeZonePrivate::Data stdData; // Transition to standard time
|
||||
auto saving = dstZone.dataAtOffset(dst.toMSecsSinceEpoch() - stdZone.offset * 1000,
|
||||
stdZone.offset);
|
||||
// Transition to standard time:
|
||||
QDateTime std(calculatePosixDate(stdDateRule, year)
|
||||
.startOfDay(QTimeZone::UTC).addSecs(stdTime));
|
||||
stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - dstZone.offset * 1000;
|
||||
stdData.offsetFromUtc = stdZone.offset;
|
||||
stdData.standardTimeOffset = stdZone.offset;
|
||||
stdData.daylightTimeOffset = 0;
|
||||
stdData.abbreviation = stdZone.name;
|
||||
auto standard = stdZone.dataAt(std.toMSecsSinceEpoch() - dstZone.offset * 1000);
|
||||
|
||||
if (year == startYear) {
|
||||
// Handle the special case of fixed state, which may be represented
|
||||
// by fake transitions at start and end of each year:
|
||||
if (dstData.atMSecsSinceEpoch < stdData.atMSecsSinceEpoch) {
|
||||
if (saving.atMSecsSinceEpoch < standard.atMSecsSinceEpoch) {
|
||||
if (dst <= QDate(year, 1, 1).startOfDay(QTimeZone::UTC)
|
||||
&& std >= QDate(year, 12, 31).endOfDay(QTimeZone::UTC)) {
|
||||
// Permanent DST:
|
||||
dstData.atMSecsSinceEpoch = lastTranMSecs;
|
||||
result << dstData;
|
||||
saving.atMSecsSinceEpoch = lastTranMSecs;
|
||||
result.emplaceBack(std::move(saving));
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
if (std <= QDate(year, 1, 1).startOfDay(QTimeZone::UTC)
|
||||
&& dst >= QDate(year, 12, 31).endOfDay(QTimeZone::UTC)) {
|
||||
// Permanent Standard time, perversely described:
|
||||
stdData.atMSecsSinceEpoch = lastTranMSecs;
|
||||
result << stdData;
|
||||
standard.atMSecsSinceEpoch = lastTranMSecs;
|
||||
result.emplaceBack(std::move(standard));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -744,14 +743,17 @@ static QList<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray
|
|||
const bool useStd = std.isValid() && std.date().year() == year && !stdZone.name.isEmpty();
|
||||
const bool useDst = dst.isValid() && dst.date().year() == year && !dstZone.name.isEmpty();
|
||||
if (useStd && useDst) {
|
||||
if (dst < std)
|
||||
result << dstData << stdData;
|
||||
else
|
||||
result << stdData << dstData;
|
||||
if (dst < std) {
|
||||
result.emplaceBack(std::move(saving));
|
||||
result.emplaceBack(std::move(standard));
|
||||
} else {
|
||||
result.emplaceBack(std::move(standard));
|
||||
result.emplaceBack(std::move(saving));
|
||||
}
|
||||
} else if (useStd) {
|
||||
result << stdData;
|
||||
result.emplaceBack(std::move(standard));
|
||||
} else if (useDst) {
|
||||
result << dstData;
|
||||
result.emplaceBack(std::move(saving));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
@ -1137,8 +1139,8 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::dataForTzTransition(QTzTransitionTime
|
|||
QTimeZonePrivate::Data QTzTimeZonePrivate::dataFromRule(QTzTransitionRule rule,
|
||||
qint64 msecsSinceEpoch) const
|
||||
{
|
||||
return { QString::fromUtf8(cached_data.m_abbreviations.at(rule.abbreviationIndex)),
|
||||
msecsSinceEpoch, rule.stdOffset + rule.dstOffset, rule.stdOffset, rule.dstOffset };
|
||||
return Data(QString::fromUtf8(cached_data.m_abbreviations.at(rule.abbreviationIndex)),
|
||||
msecsSinceEpoch, rule.stdOffset + rule.dstOffset, rule.stdOffset);
|
||||
}
|
||||
|
||||
QList<QTimeZonePrivate::Data> QTzTimeZonePrivate::getPosixTransitions(qint64 msNear) const
|
||||
|
|
@ -1168,7 +1170,7 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
|
|||
}
|
||||
}
|
||||
if (tranCache().isEmpty()) // Only possible if !isValid()
|
||||
return invalidData();
|
||||
return {};
|
||||
|
||||
// Otherwise, use the rule for the most recent or first transition:
|
||||
auto last = std::partition_point(tranCache().cbegin(), tranCache().cend(),
|
||||
|
|
@ -1199,7 +1201,7 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSince
|
|||
return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch;
|
||||
});
|
||||
|
||||
return it == posixTrans.cend() ? invalidData() : *it;
|
||||
return it == posixTrans.cend() ? Data{} : *it;
|
||||
}
|
||||
|
||||
// Otherwise, if we can find a valid tran, use its rule:
|
||||
|
|
@ -1207,7 +1209,7 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSince
|
|||
[afterMSecsSinceEpoch] (const QTzTransitionTime &at) {
|
||||
return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch;
|
||||
});
|
||||
return last != tranCache().cend() ? dataForTzTransition(*last) : invalidData();
|
||||
return last != tranCache().cend() ? dataForTzTransition(*last) : Data{};
|
||||
}
|
||||
|
||||
QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
|
||||
|
|
@ -1224,7 +1226,7 @@ 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 tranCache().isEmpty() ? invalidData() : dataForTzTransition(tranCache().last());
|
||||
return tranCache().isEmpty() ? Data{} : dataForTzTransition(tranCache().last());
|
||||
}
|
||||
|
||||
// Otherwise if we can find a valid tran then use its rule
|
||||
|
|
@ -1232,7 +1234,7 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecs
|
|||
[beforeMSecsSinceEpoch] (const QTzTransitionTime &at) {
|
||||
return at.atMSecsSinceEpoch < beforeMSecsSinceEpoch;
|
||||
});
|
||||
return last > tranCache().cbegin() ? dataForTzTransition(*--last) : invalidData();
|
||||
return last > tranCache().cbegin() ? dataForTzTransition(*--last) : Data{};
|
||||
}
|
||||
|
||||
bool QTzTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const
|
||||
|
|
|
|||
|
|
@ -692,7 +692,7 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::data(qint64 forMSecsSinceEpoch) cons
|
|||
// Fell off start of rule, try previous rule.
|
||||
}
|
||||
// We don't have relevant data :-(
|
||||
return invalidData();
|
||||
return {};
|
||||
}
|
||||
|
||||
bool QWinTimeZonePrivate::hasTransitions() const
|
||||
|
|
@ -774,13 +774,13 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::nextTransition(qint64 afterMSecsSinc
|
|||
}
|
||||
}
|
||||
// Apparently no transition after the given time:
|
||||
return invalidData();
|
||||
return {};
|
||||
}
|
||||
|
||||
QTimeZonePrivate::Data QWinTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
|
||||
{
|
||||
if (beforeMSecsSinceEpoch <= minMSecs())
|
||||
return invalidData();
|
||||
return {};
|
||||
|
||||
int year = msecsToDate(beforeMSecsSinceEpoch).year();
|
||||
for (int ruleIndex = ruleIndexForYear(m_tranRules, year);
|
||||
|
|
@ -830,7 +830,7 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::previousTransition(qint64 beforeMSec
|
|||
}
|
||||
}
|
||||
// Apparently no transition before the given time:
|
||||
return invalidData();
|
||||
return {};
|
||||
}
|
||||
|
||||
QByteArray QWinTimeZonePrivate::systemTimeZoneId() const
|
||||
|
|
@ -866,7 +866,7 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::ruleToData(const QWinTransitionRule
|
|||
QTimeZone::TimeType type,
|
||||
bool fakeDst) const
|
||||
{
|
||||
Data tran = invalidData();
|
||||
Data tran;
|
||||
tran.atMSecsSinceEpoch = atMSecsSinceEpoch;
|
||||
tran.standardTimeOffset = rule.standardTimeBias * -60;
|
||||
if (fakeDst) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue