Rearrange mapLocalTime() so its millis always have the right sign
Doing a simple division to get seconds, before using rounding-down division to get days and positive seconds, saves the need to check for seconds and millis in opposite directions that might cause a needless overflow when computing the final result. Change-Id: Ia4f95bb0510eb4f2c1f9131a34d317bd41bbed2a Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
854cb55987
commit
0acb56518d
@ -348,11 +348,13 @@ QString localTimeAbbbreviationAt(qint64 local, QDateTimePrivate::DaylightStatus
|
|||||||
|
|
||||||
QDateTimePrivate::ZoneState mapLocalTime(qint64 local, QDateTimePrivate::DaylightStatus dst)
|
QDateTimePrivate::ZoneState mapLocalTime(qint64 local, QDateTimePrivate::DaylightStatus dst)
|
||||||
{
|
{
|
||||||
const qint64 localDays = QRoundingDown::qDiv(local, MSECS_PER_DAY);
|
qint64 localSecs = local / MSECS_PER_SEC;
|
||||||
qint64 millis = local - localDays * MSECS_PER_DAY;
|
qint64 millis = local - localSecs * MSECS_PER_SEC; // 0 or with same sign as local
|
||||||
Q_ASSERT(0 <= millis && millis < MSECS_PER_DAY); // Definition of QRD::qDiv.
|
const qint64 localDays = QRoundingDown::qDiv(localSecs, SECS_PER_DAY);
|
||||||
struct tm tmLocal = timeToTm(localDays, int(millis / MSECS_PER_SEC), dst);
|
qint64 daySecs = localSecs - localDays * SECS_PER_DAY;
|
||||||
millis %= MSECS_PER_SEC;
|
Q_ASSERT(0 <= daySecs && daySecs < SECS_PER_DAY); // Definition of QRD::qDiv.
|
||||||
|
|
||||||
|
struct tm tmLocal = timeToTm(localDays, daySecs, dst);
|
||||||
time_t utcSecs;
|
time_t utcSecs;
|
||||||
if (!callMkTime(&tmLocal, &utcSecs))
|
if (!callMkTime(&tmLocal, &utcSecs))
|
||||||
return {local};
|
return {local};
|
||||||
@ -368,22 +370,21 @@ QDateTimePrivate::ZoneState mapLocalTime(qint64 local, QDateTimePrivate::Dayligh
|
|||||||
&jd))) {
|
&jd))) {
|
||||||
return {local, offset, dst, false};
|
return {local, offset, dst, false};
|
||||||
}
|
}
|
||||||
qint64 daySecs = tmSecsWithinDay(tmLocal);
|
daySecs = tmSecsWithinDay(tmLocal);
|
||||||
Q_ASSERT(0 <= daySecs && daySecs < SECS_PER_DAY);
|
Q_ASSERT(0 <= daySecs && daySecs < SECS_PER_DAY);
|
||||||
if (daySecs > 0 && jd < JULIAN_DAY_FOR_EPOCH) {
|
if (daySecs > 0 && jd < JULIAN_DAY_FOR_EPOCH) {
|
||||||
++jd;
|
++jd;
|
||||||
daySecs -= SECS_PER_DAY;
|
daySecs -= SECS_PER_DAY;
|
||||||
}
|
}
|
||||||
qint64 localSecs;
|
|
||||||
if (Q_UNLIKELY(daysAndSecondsOverflow(jd, daySecs, &localSecs)))
|
if (Q_UNLIKELY(daysAndSecondsOverflow(jd, daySecs, &localSecs)))
|
||||||
return {local, offset, dst, false};
|
return {local, offset, dst, false};
|
||||||
|
|
||||||
offset = localSecs - utcSecs;
|
offset = localSecs - utcSecs;
|
||||||
|
|
||||||
if (localSecs < 0 && millis > 0) {
|
// The only way localSecs and millis can now have opposite sign is for
|
||||||
++localSecs;
|
// resolution of the local time to have kicked us across the epoch, in which
|
||||||
millis -= MSECS_PER_SEC;
|
// case there's no danger of overflow. So if overflow is in danger of
|
||||||
}
|
// happening, we're already doing the best we can to avoid it.
|
||||||
qint64 revised;
|
qint64 revised;
|
||||||
const bool overflow = secondsAndMillisOverflow(localSecs, millis, &revised);
|
const bool overflow = secondsAndMillisOverflow(localSecs, millis, &revised);
|
||||||
return {overflow ? local : revised, offset, dst, !overflow};
|
return {overflow ? local : revised, offset, dst, !overflow};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user