Fix problem with Australasian zones in fromSecsSinceEpoch() test

It seems glibc's extrapolation of existing DST-rules cuts off at some
point in the distant future, where the IANA DB gives no end-time for
such rules, leading QTimeZone to keep applying them.  This lead to
tst_QDateTime::fromSecsSinceEpoch() not getting an invalid date in one
of its bounds-probing tests, due to a within-bounds datetime getting
glibc's offset and then the out-of-bounds one falling back to the IANA
rule's offset that put it back within the bounds.

This directly affected Australasian zones (which glibc locks into
daylight-saving time in this distant future) which were fixed by using
the IANA DB's offset; but the relevant date is in August so other
zones, north of the equator, that glibc locks into standard time, then
had the reverse problem, so we have to take the minimum of the two
sources' offsets to get all zones on board.

Change-Id: I0c94af2ba108dea31bee46aafa4a8cca8d373a5c
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Konrad Kujawa <konrad.kujawa@qt.io>
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
This commit is contained in:
Edward Welbourne 2023-04-24 17:09:44 +02:00
parent 6aea6c25a5
commit c888153655

View File

@ -930,7 +930,22 @@ void tst_QDateTime::fromSecsSinceEpoch()
QVERIFY(!QDateTime::fromSecsSinceEpoch(-maxSeconds - 1, UTC).isValid());
// Local time: need to adjust for its zone offset
const qint64 last = maxSeconds - qMax(late.addYears(-1).toLocalTime().offsetFromUtc(), 0);
const int lateOffset = late.addYears(-1).toLocalTime().offsetFromUtc();
#if QT_CONFIG(timezone)
// Check what system zone believes in, as it's used as fall-back to cope
// with times outside the system time_t functions' range, or overflow on the
// results of using those functions. (It seems glibc's handling of
// Australasian zones parts company with the IANA DB after about 5881580 CE,
// leaving NZ in permanent DST after that, for example.) Of course, if
// that's less than lateOffset (as it is for glibc's similar handling of
// MET), the fall-back code will also fail when the primary code fails, so
// use the lesser of these late offsets.
const int lateZone = qMin(QTimeZone::systemTimeZone().offsetFromUtc(late), lateOffset);
#else
const int lateZone = lateOffset;
#endif
const qint64 last = maxSeconds - qMax(lateZone, 0);
QVERIFY(QDateTime::fromSecsSinceEpoch(last).isValid());
QVERIFY(!QDateTime::fromSecsSinceEpoch(last + 1).isValid());
const qint64 first = -maxSeconds - qMin(early.addYears(1).toLocalTime().offsetFromUtc(), 0);