Kludge round macOS 15 knowing more about offsets than transitions

Darwin turns out to know about offset changes a million years into the
future, but to not admit to there being any transitions more than (a
bit over) half a million years into the future. It thus failed the
non-ShortData part of tst_QDateTime::timeZones(), thanks to using
correct offsets that showed there must be a transition in the
interval, but not believing in that transition.

The discrepancy leads to QTimeZonePrivate::stateAtZoneTime() getting
valid data for before and after the transition, with different
offsets, so amend its "no later transitions" early return to check the
offsets do in fact match. If they don't fall back on the code that
handles the case where we don't know about transitions but do have
offset data.

Pick-to: 6.7
Fixes: QTBUG-126391
Change-Id: Iefda439377ebc3025f2b754e2ec686fcc6361a1b
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit cb870adad612018e7007f4a1b6066b49d0f2dc4a)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Edward Welbourne 2024-07-05 13:27:16 +02:00 committed by Qt Cherry-pick Bot
parent 1407e54f34
commit bc28d6d48c

View File

@ -416,6 +416,7 @@ QDateTimePrivate::ZoneState QTimeZonePrivate::stateAtZoneTime(
tran = nextTran;
nextTran = newTran;
}
const qint64 nextStart = nextTran.atMSecsSinceEpoch;
// Check we do *really* have transitions for this zone:
if (tran.atMSecsSinceEpoch != invalidMSecs()) {
@ -424,11 +425,18 @@ QDateTimePrivate::ZoneState QTimeZonePrivate::stateAtZoneTime(
|| 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;
if (nextStart == invalidMSecs())
return dataToState(tran); // Last valid transition.
// If there are no transition after it, the answer is easy - or
// should be - but Darwin's handling of the distant future (in macOS
// 15, QTBUG-126391) runs out of transitions in 506'712 CE, despite
// knowing about offset changes long after that. So only trust the
// easy answer if offsets match; otherwise, fall through to the
// transitions-unknown code.
if (nextStart == invalidMSecs() && tran.offsetFromUtc == future.offsetFromUtc)
return dataToState(tran); // Last valid transition.
}
if (tran.atMSecsSinceEpoch != invalidMSecs() && nextStart != invalidMSecs()) {
/*
... and nextTran is either after or only slightly before. We're
going to interpret one as standard time, the other as DST