diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp index 861ebefbdf..8d0cb80a18 100644 --- a/src/corelib/time/qtimezoneprivate.cpp +++ b/src/corelib/time/qtimezoneprivate.cpp @@ -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; diff --git a/src/corelib/time/qtimezoneprivate_android.cpp b/src/corelib/time/qtimezoneprivate_android.cpp index 0194352f5e..47fc68b1ac 100644 --- a/src/corelib/time/qtimezoneprivate_android.cpp +++ b/src/corelib/time/qtimezoneprivate_android.cpp @@ -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, diff --git a/src/corelib/time/qtimezoneprivate_icu.cpp b/src/corelib/time/qtimezoneprivate_icu.cpp index 2a2770d3ea..1a3baa70d0 100644 --- a/src/corelib/time/qtimezoneprivate_icu.cpp +++ b/src/corelib/time/qtimezoneprivate_icu.cpp @@ -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 } diff --git a/src/corelib/time/qtimezoneprivate_mac.mm b/src/corelib/time/qtimezoneprivate_mac.mm index 8bc48f893b..da7e24d614 100644 --- a/src/corelib/time/qtimezoneprivate_mac.mm +++ b/src/corelib/time/qtimezoneprivate_mac.mm @@ -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 diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h index 53da9693ca..4ad51f44e7 100644 --- a/src/corelib/time/qtimezoneprivate_p.h +++ b/src/corelib/time/qtimezoneprivate_p.h @@ -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 DataList; @@ -112,7 +125,6 @@ public: { return (std::numeric_limits::min)(); } [[nodiscard]] static constexpr qint64 invalidSeconds() { return (std::numeric_limits::min)(); } - static Data invalidData(); static QTimeZone::OffsetData invalidOffsetData(); static QTimeZone::OffsetData toOffsetData(const Data &data); static bool isValidId(const QByteArray &ianaId); diff --git a/src/corelib/time/qtimezoneprivate_tz.cpp b/src/corelib/time/qtimezoneprivate_tz.cpp index 8c6a32edc9..fce9deaa33 100644 --- a/src/corelib/time/qtimezoneprivate_tz.cpp +++ b/src/corelib/time/qtimezoneprivate_tz.cpp @@ -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 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 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 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 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 diff --git a/src/corelib/time/qtimezoneprivate_win.cpp b/src/corelib/time/qtimezoneprivate_win.cpp index 2502516810..7874c22174 100644 --- a/src/corelib/time/qtimezoneprivate_win.cpp +++ b/src/corelib/time/qtimezoneprivate_win.cpp @@ -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) {