summaryrefslogtreecommitdiffstats
path: root/src/corelib/time
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2021-08-31 16:48:37 +0200
committerEdward Welbourne <edward.welbourne@qt.io>2021-09-01 11:26:54 +0200
commitb656cea5deccab352b7c4c56d7023f5108578654 (patch)
tree73384b46bd96fdc18831cb718d13e4c3c7447e56 /src/corelib/time
parent5598a15fe7507e7638449598fa5a8aadd95ef350 (diff)
Fix corner case in QTimeZonePrivate::dataForLocalTime()
If the local time for which we want data is after the last known transition, the two transitions we get to bracket it are the last known and an invalid one. The code checked the former was valid, but neglected to check the latter, leading to nonsense arithmetic later in the function. In this situation we unequivocally want the last known transition, so the problem is easily solved. Fixes: QTBUG-96152 Pick-to: 6.2 6.1 5.15 5.12 Change-Id: I6fc830ce538e8a572093cd8dfe832e10689bf904 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src/corelib/time')
-rw-r--r--src/corelib/time/qtimezoneprivate.cpp32
1 files changed, 18 insertions, 14 deletions
diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp
index 2884807b96..b1f76d772d 100644
--- a/src/corelib/time/qtimezoneprivate.cpp
+++ b/src/corelib/time/qtimezoneprivate.cpp
@@ -376,22 +376,27 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
// Check we do *really* have transitions for this zone:
if (tran.atMSecsSinceEpoch != invalidMSecs()) {
-
- /*
- So now tran is definitely before and nextTran is either after or
- only slightly before. We're going to interpret one as standard
- time, the other as DST (although the transition might in fact by a
- change in standard offset, or a chance in DST offset, e.g. to/from
- double-DST). Our hint tells us which of those to use (defaulting
- to standard if no hint): try it first; if that fails, try the
- other; if both fail, life's tricky.
- */
+ /* So now tran is definitely before ... */
Q_ASSERT(forLocalMSecs < 0
|| forLocalMSecs - tran.offsetFromUtc * 1000 > tran.atMSecsSinceEpoch);
+ // Work out the UTC value it would make sense to return if using tran:
+ tran.atMSecsSinceEpoch = forLocalMSecs - tran.offsetFromUtc * 1000;
+ // If we know of no transition after it, the answer is easy:
const qint64 nextStart = nextTran.atMSecsSinceEpoch;
- // Work out the UTC values it might make sense to return:
+ if (nextStart == invalidMSecs())
+ return tran;
+
+ /*
+ ... and nextTran is either after or only slightly before. We're
+ going to interpret one as standard time, the other as DST
+ (although the transition might in fact be a change in standard
+ offset, or a change in DST offset, e.g. to/from double-DST). Our
+ hint tells us which of those to use (defaulting to standard if no
+ hint): try it first; if that fails, try the other; if both fail,
+ life's tricky.
+ */
+ // Work out the UTC value it would make sense to return if using nextTran:
nextTran.atMSecsSinceEpoch = forLocalMSecs - nextTran.offsetFromUtc * 1000;
- tran.atMSecsSinceEpoch = forLocalMSecs - tran.offsetFromUtc * 1000;
// If both or neither have zero DST, treat the one with lower offset as standard:
const bool nextIsDst = !nextTran.daylightTimeOffset == !tran.daylightTimeOffset
@@ -406,12 +411,11 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
by which time the second case, that we're trying, is likely right.
*/
if (nextFirst ? i == 0 : i) {
- Q_ASSERT(nextStart != invalidMSecs());
if (nextStart <= nextTran.atMSecsSinceEpoch)
return nextTran;
} else {
// If next is invalid, nextFirst is false, to route us here first:
- if (nextStart == invalidMSecs() || nextStart > tran.atMSecsSinceEpoch)
+ if (nextStart > tran.atMSecsSinceEpoch)
return tran;
}
}