diff options
author | Edward Welbourne <edward.welbourne@qt.io> | 2022-01-25 15:53:48 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-01-30 22:11:08 +0000 |
commit | 574fc358e70b0d5149cb2ffb98118ced71e7d5c2 (patch) | |
tree | a23ee6d2e64d81bc304da64190e6a9bddfcba026 | |
parent | 6801c18813d8521fda44515cc9ee745c1b9bf85f (diff) |
Fix misguided winding backwards past start of start of MS TZ datav6.3.0-beta1
QWinTimeZonePrivate::data()'s search for a rule applicable to a given
time, in the first year whose milliseconds qint64 can represent, tries
to look at the preceding year to get start-of-year data, which leads
to misleading results. It does so to determine whether to use a rule's
standard or daylight-saving details, but this year is long before the
invention of daylight-saving time, so we can bypass the whole mess.
Unfortunately, MS's data does pretend (in some zones) that DST has
always been in effect, so cutting off that claim at some historical
point will actually get better results for before the cut-off than for
the period after it, until the relevant zone actually adopted DST.
Conservatively put the cut-off at 1900, before any actual zone used
DST, albeit after the idea was originally floated.
This fixes a failure found by some QDate::{start,end}OfDay() tests
that I want to introduce.
Task-number: QTBUG-99747
Change-Id: I15cf9dd092b946191e8863c7e85fbeb4ba6c106d
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
(cherry picked from commit 9a83706046406f233ea6f93a2f90fd5b05916ee9)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/corelib/time/qtimezoneprivate_win.cpp | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/src/corelib/time/qtimezoneprivate_win.cpp b/src/corelib/time/qtimezoneprivate_win.cpp index ff8cd5548e..06524f1189 100644 --- a/src/corelib/time/qtimezoneprivate_win.cpp +++ b/src/corelib/time/qtimezoneprivate_win.cpp @@ -73,6 +73,22 @@ static const wchar_t currTzRegPath[] = LR"(SYSTEM\CurrentControlSet\Control\Time constexpr qint64 MSECS_PER_DAY = 86400000LL; constexpr qint64 JULIAN_DAY_FOR_EPOCH = 2440588LL; // result of julianDayFromDate(1970, 1, 1) +/* Ignore any claims of DST before 1900. + + Daylight-Saving time adjustments were first proposed in 1895 (George Vernon + Hudson in New Zealand) and 1905 (William Willett in the UK) and first adopted + in 1908 (one town in Ontario, Canada) and 1916 (Germany). Since MS's data + tends to pretend the rules in force in 1970ish (or later) had always been in + effect, which presents difficulties for the code that selects correct data + (for a time close to the earliest we can represent), always ignore any claims + a first rule may make of DST before 1900. + + See: + * https://www.timeanddate.com/time/dst/history.html + * https://en.wikipedia.org/wiki/Daylight_saving_time#History +*/ +constexpr int FIRST_DST_YEAR = 1900; + // Copied from MSDN, see above for link typedef struct _REG_TZI_FORMAT { @@ -606,7 +622,11 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::data(qint64 forMSecsSinceEpoch) cons : yearEndOffset(rule, prior); const TransitionTimePair pair(rule, year, newYearOffset); bool isDst = false; - if (pair.std != invalidMSecs() && pair.std <= forMSecsSinceEpoch) { + if (!ruleIndex && year < FIRST_DST_YEAR) { + // We're before the invention of DST and have no earlier + // rule that might give better data on this year, so just + // extrapolate standard time (modulo fakery) backwards. + } else if (pair.std != invalidMSecs() && pair.std <= forMSecsSinceEpoch) { isDst = pair.std < pair.dst && pair.dst <= forMSecsSinceEpoch; } else if (pair.dst != invalidMSecs() && pair.dst <= forMSecsSinceEpoch) { isDst = true; |