From 4959f8a34b6eacd7c726d9166d04954376a7e5bf Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 23 Feb 2022 12:22:44 +0100 Subject: [PATCH] Clip dataForLocalTime()'s bracketing window's start to minMSecs() + 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The minMSecs() itself is one more than the type's min(), which is used as invalidMSecs(). As (at least) the Windows back-end uses minMSecs() as the time of a start-of-time transition (that we'd like to find as our current transition), use one more than it as lower-bound for where to search from for a previous transition, so that we do find that first ever transition. Pick-to: 6.3 Change-Id: Iae861e740e02bd38ffb2af77aff625d3b48182d2 Reviewed-by: MÃ¥rten Nordheim --- src/corelib/time/qtimezoneprivate.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp index a85617718d..e3f392230a 100644 --- a/src/corelib/time/qtimezoneprivate.cpp +++ b/src/corelib/time/qtimezoneprivate.cpp @@ -225,14 +225,18 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs, static_assert(-sixteenHoursInMSecs / 1000 < QTimeZone::MinUtcOffsetSecs && sixteenHoursInMSecs / 1000 > QTimeZone::MaxUtcOffsetSecs); qint64 millis; + // Clip the bracketing times to the bounds of the supported range. Exclude + // minMSecs(), because at least one backend (Windows) uses it for a + // start-of-time fake transition, that we want previousTransition() to find. const qint64 recent = - sub_overflow(forLocalMSecs, sixteenHoursInMSecs, &millis) - ? minMSecs() : millis; + sub_overflow(forLocalMSecs, sixteenHoursInMSecs, &millis) || millis <= minMSecs() + ? minMSecs() + 1 : millis; // Necessarily <= forLocalMSecs + 2. + // (Given that minMSecs() is std::numeric_limits::min() + 1.) const qint64 imminent = add_overflow(forLocalMSecs, sixteenHoursInMSecs, &millis) - ? maxMSecs() : millis; - // At most one of those took the boundary value: - Q_ASSERT(recent < imminent && sixteenHoursInMSecs < imminent - recent + 1); + ? maxMSecs() : millis; // Necessarily >= forLocalMSecs + // At most one of those was clipped to its boundary value: + Q_ASSERT(recent < imminent && sixteenHoursInMSecs < imminent - recent + 2); /* Offsets are Local - UTC, positive to the east of Greenwich, negative to the west; DST offset always exceeds standard offset, when DST applies.