summaryrefslogtreecommitdiffstats
path: root/src/corelib/time
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2021-08-31 16:48:37 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-09-01 12:07:00 +0000
commit8ae5f758a63390fb2649ca773741e0bfa6bfcfe8 (patch)
tree236fedc84c849e6bc260063878d8c427c5413f94 /src/corelib/time
parent3fd07467c9cfcb854d3ab220ddb7c4868bbb2f72 (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 Change-Id: I6fc830ce538e8a572093cd8dfe832e10689bf904 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io> (cherry picked from commit b656cea5deccab352b7c4c56d7023f5108578654) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
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 2e2079255d..34297bcaea 100644
--- a/src/corelib/time/qtimezoneprivate.cpp
+++ b/src/corelib/time/qtimezoneprivate.cpp
@@ -384,22 +384,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
@@ -414,12 +419,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;
}
}