summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/time/qdatetime.cpp41
-rw-r--r--src/corelib/time/qdatetime_p.h3
2 files changed, 25 insertions, 19 deletions
diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp
index c6a41855b0..af77a0ee26 100644
--- a/src/corelib/time/qdatetime.cpp
+++ b/src/corelib/time/qdatetime.cpp
@@ -874,7 +874,10 @@ QDateTime QDate::startOfDay(const QTimeZone &zone) const
// The start of the day must have fallen in a spring-forward's gap; find the spring-forward:
if (zone.hasTransitions()) {
- QTimeZone::OffsetData tran = zone.previousTransition(QDateTime(*this, QTime(23, 59, 59, 999), zone));
+ QTimeZone::OffsetData tran
+ // There's unlikely to be another transition before noon tomorrow.
+ // However, the whole of today may have been skipped !
+ = zone.previousTransition(QDateTime(addDays(1), QTime(12, 0), zone));
const QDateTime &at = tran.atUtc.toTimeZone(zone);
if (at.isValid() && at.date() == *this)
return at;
@@ -997,7 +1000,10 @@ QDateTime QDate::endOfDay(const QTimeZone &zone) const
// The end of the day must have fallen in a spring-forward's gap; find the spring-forward:
if (zone.hasTransitions()) {
- QTimeZone::OffsetData tran = zone.nextTransition(QDateTime(*this, QTime(0, 0), zone));
+ QTimeZone::OffsetData tran
+ // It's unlikely there's been another transition since yesterday noon.
+ // However, the whole of today may have been skipped !
+ = zone.nextTransition(QDateTime(addDays(-1), QTime(12, 0), zone));
const QDateTime &at = tran.atUtc.toTimeZone(zone);
if (at.isValid() && at.date() == *this)
return at;
@@ -2794,13 +2800,6 @@ static inline bool usesSameOffset(const QDateTimeData &a, const QDateTimeData &b
return false;
}
-#if QT_CONFIG(timezone)
-void QDateTimePrivate::setUtcOffsetByTZ(qint64 atMSecsSinceEpoch)
-{
- m_offsetFromUtc = m_timeZone.d->offsetFromUtc(atMSecsSinceEpoch);
-}
-#endif
-
// Refresh the LocalTime or TimeZone validity and offset
static void refreshZonedDateTime(QDateTimeData &d, Qt::TimeSpec spec)
{
@@ -2829,14 +2828,13 @@ static void refreshZonedDateTime(QDateTimeData &d, Qt::TimeSpec spec)
} else if (d->m_timeZone.isValid()) {
epochMSecs = QDateTimePrivate::zoneMSecsToEpochMSecs(
msecs, d->m_timeZone, extractDaylightStatus(status), &testDate, &testTime);
- d->setUtcOffsetByTZ(epochMSecs);
#endif // timezone
} // else: testDate, testTime haven't been set, so are invalid.
+ // Cache the offset to use in offsetFromUtc() &c.
+ offsetFromUtc = (msecs - epochMSecs) / 1000;
if (testDate.isValid() && testTime.isValid()
&& timeToMSecs(testDate, testTime) == msecs) {
status |= QDateTimePrivate::ValidDateTime;
- // Cache the offset to use in offsetFromUtc()
- offsetFromUtc = (msecs - epochMSecs) / 1000;
} else {
status &= ~QDateTimePrivate::ValidDateTime;
}
@@ -3155,6 +3153,12 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
Q_ASSERT(zone.isValid());
// Get the effective data from QTimeZone
QTimeZonePrivate::Data data = zone.d->dataForLocalTime(zoneMSecs, int(hint));
+ Q_ASSERT(zone.d->offsetFromUtc(data.atMSecsSinceEpoch) == data.offsetFromUtc);
+ Q_ASSERT((zoneMSecs - data.atMSecsSinceEpoch) / 1000 == data.offsetFromUtc
+ // If zoneMSecs fell in a spring-forward's gap, we get this instead:
+ || (zoneMSecs - data.atMSecsSinceEpoch) / 1000 == data.standardTimeOffset
+ // If it fell in a skipped day (Pacific date-line crossings), this happens:
+ || (data.offsetFromUtc - (zoneMSecs - data.atMSecsSinceEpoch) / 1000) % 86400 == 0);
// Docs state any time before 1970-01-01 will *not* have any DST applied
// but all affected times afterwards will have DST applied.
if (data.atMSecsSinceEpoch < 0) {
@@ -3772,20 +3776,25 @@ qint64 QDateTime::toMSecsSinceEpoch() const
return getMSecs(d);
case Qt::OffsetFromUTC:
+ Q_ASSERT(!d.isShort());
return d->m_msecs - (d->m_offsetFromUtc * 1000);
case Qt::LocalTime: {
// recalculate the local timezone
auto status = extractDaylightStatus(getStatus(d));
+ // If short, use offset saved by refreshZonedDateTime() on creation:
+ if (!d.isShort())
+ return d->m_msecs - d->m_offsetFromUtc * 1000;
+ // Offset from UTC not recorded: need to recompute.
return localMSecsToEpochMSecs(getMSecs(d), &status);
}
case Qt::TimeZone:
+ Q_ASSERT(!d.isShort());
#if QT_CONFIG(timezone)
- if (d->m_timeZone.isValid()) {
- return QDateTimePrivate::zoneMSecsToEpochMSecs(d->m_msecs, d->m_timeZone,
- extractDaylightStatus(getStatus(d)));
- }
+ // Use offset refreshZonedDateTime() saved creation:
+ if (d->m_timeZone.isValid())
+ return d->m_msecs - d->m_offsetFromUtc * 1000;
#endif
return 0;
}
diff --git a/src/corelib/time/qdatetime_p.h b/src/corelib/time/qdatetime_p.h
index c500b023c4..2b690841ee 100644
--- a/src/corelib/time/qdatetime_p.h
+++ b/src/corelib/time/qdatetime_p.h
@@ -128,9 +128,6 @@ public:
static qint64 zoneMSecsToEpochMSecs(qint64 msecs, const QTimeZone &zone,
DaylightStatus hint = UnknownDaylightTime,
QDate *localDate = nullptr, QTime *localTime = nullptr);
-
- // Inlined for its one caller in qdatetime.cpp
- inline void setUtcOffsetByTZ(qint64 atMSecsSinceEpoch);
#endif // timezone
};