summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2022-01-25 15:53:48 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-01-30 22:11:08 +0000
commit574fc358e70b0d5149cb2ffb98118ced71e7d5c2 (patch)
treea23ee6d2e64d81bc304da64190e6a9bddfcba026
parent6801c18813d8521fda44515cc9ee745c1b9bf85f (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.cpp22
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;