Rework setMSecsSinceEpoch() to avoid local->UTC conversions
The function takes a UTC time, which it converts to local time when needed, but its (two) calls to refresh a local time instance were doing the (more expensive) reverse conversion, which we don't need (because we knew UTC to start with) and, in this case, it can't land on an invalid time, so we don't need to cope with that. Change-Id: I49b42bfa9f6a5fde12810f5a0da9ff4466ca86a4 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
This commit is contained in:
parent
fd5b92c2ba
commit
74eddd5bf0
@ -4005,63 +4005,60 @@ void QDateTime::setMSecsSinceEpoch(qint64 msecs)
|
||||
{
|
||||
auto status = getStatus(d);
|
||||
const auto spec = extractSpec(status);
|
||||
Q_ASSERT(spec == Qt::UTC || spec == Qt::LocalTime || !d.isShort());
|
||||
qint64 local = msecs;
|
||||
int offsetFromUtc = 0;
|
||||
|
||||
status &= ~QDateTimePrivate::ValidityMask;
|
||||
switch (spec) {
|
||||
case Qt::UTC:
|
||||
status |= QDateTimePrivate::ValidWhenMask;
|
||||
break;
|
||||
case Qt::OffsetFromUTC:
|
||||
if (!add_overflow(msecs, d->m_offsetFromUtc * MSECS_PER_SEC, &msecs))
|
||||
if (spec == Qt::UTC || spec == Qt::OffsetFromUTC) {
|
||||
if (spec == Qt::OffsetFromUTC)
|
||||
offsetFromUtc = d->m_offsetFromUtc;
|
||||
if (!offsetFromUtc || !add_overflow(msecs, offsetFromUtc * MSECS_PER_SEC, &local))
|
||||
status |= QDateTimePrivate::ValidWhenMask;
|
||||
break;
|
||||
case Qt::TimeZone:
|
||||
Q_ASSERT(!d.isShort());
|
||||
#if QT_CONFIG(timezone)
|
||||
d.detach();
|
||||
if (!d->m_timeZone.isValid())
|
||||
break;
|
||||
status = mergeDaylightStatus(status,
|
||||
d->m_timeZone.d->isDaylightTime(msecs)
|
||||
? QDateTimePrivate::DaylightTime
|
||||
: QDateTimePrivate::StandardTime);
|
||||
d->m_offsetFromUtc = d->m_timeZone.d->offsetFromUtc(msecs);
|
||||
// NB: cast to qint64 here is important to make sure a matching
|
||||
// add_overflow is found, GCC 7.5.0 fails without this cast
|
||||
if (!add_overflow(msecs, qint64(d->m_offsetFromUtc * MSECS_PER_SEC), &msecs))
|
||||
status |= QDateTimePrivate::ValidWhenMask;
|
||||
#endif // timezone
|
||||
break;
|
||||
case Qt::LocalTime: {
|
||||
QDate dt;
|
||||
QTime tm;
|
||||
QDateTimePrivate::DaylightStatus dstStatus;
|
||||
if (QDateTimePrivate::epochMSecsToLocalTime(msecs, &dt, &tm, &dstStatus)) {
|
||||
setDateTime(d, dt, tm);
|
||||
} else {
|
||||
auto dst = extractDaylightStatus(status);
|
||||
if (spec == Qt::LocalTime) {
|
||||
QDate dt;
|
||||
QTime tm;
|
||||
if (QDateTimePrivate::epochMSecsToLocalTime(msecs, &dt, &tm, &dst))
|
||||
setDateTime(d, dt, tm);
|
||||
status = getStatus(d);
|
||||
if ((status & QDateTimePrivate::ValidDate) && (status & QDateTimePrivate::ValidTime)) {
|
||||
local = getMSecs(d);
|
||||
offsetFromUtc = (local - msecs) / MSECS_PER_SEC;
|
||||
status |= QDateTimePrivate::ValidWhenMask;
|
||||
}
|
||||
#if QT_CONFIG(timezone)
|
||||
} else if (spec == Qt::TimeZone && (d.detach(), d->m_timeZone.isValid())) {
|
||||
const auto data = d->m_timeZone.d->data(msecs);
|
||||
if (data.offsetFromUtc != QTimeZonePrivate::invalidSeconds()) {
|
||||
dst = data.daylightTimeOffset
|
||||
? QDateTimePrivate::DaylightTime
|
||||
: QDateTimePrivate::StandardTime;
|
||||
offsetFromUtc = data.offsetFromUtc;
|
||||
if (!offsetFromUtc
|
||||
// NB: cast to qint64 here is important to make sure a matching
|
||||
// add_overflow is found, GCC 7.5.0 fails without this cast
|
||||
|| !add_overflow(msecs, qint64(offsetFromUtc * MSECS_PER_SEC), &local)) {
|
||||
status |= QDateTimePrivate::ValidWhenMask;
|
||||
}
|
||||
}
|
||||
#endif // timezone
|
||||
}
|
||||
if ((status & QDateTimePrivate::ValidDate) && (status & QDateTimePrivate::ValidTime)) {
|
||||
refreshZonedDateTime(d, spec); // FIXME: we do this again, below
|
||||
msecs = getMSecs(d);
|
||||
status = mergeDaylightStatus(getStatus(d), dstStatus);
|
||||
}
|
||||
break;
|
||||
}
|
||||
status = mergeDaylightStatus(status, dst);
|
||||
}
|
||||
Q_ASSERT(!(status & QDateTimePrivate::ValidDateTime)
|
||||
|| (offsetFromUtc >= -SECS_PER_DAY && offsetFromUtc <= SECS_PER_DAY));
|
||||
|
||||
if (msecsCanBeSmall(msecs) && d.isShort()) {
|
||||
if (msecsCanBeSmall(local) && d.isShort()) {
|
||||
// we can keep short
|
||||
d.data.msecs = qintptr(msecs);
|
||||
d.data.msecs = qintptr(local);
|
||||
d.data.status = status.toInt();
|
||||
} else {
|
||||
d.detach();
|
||||
d->m_status = status & ~QDateTimePrivate::ShortData;
|
||||
d->m_msecs = msecs;
|
||||
}
|
||||
|
||||
if (spec == Qt::LocalTime || spec == Qt::TimeZone) {
|
||||
refreshZonedDateTime(d, spec);
|
||||
Q_ASSERT((d.isShort() ? d.data.msecs : d->m_msecs) == msecs);
|
||||
d->m_msecs = local;
|
||||
d->m_offsetFromUtc = offsetFromUtc;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user