Fix misguided winding backwards past start of start of MS TZ data
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. Pick-to: 6.3 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>
This commit is contained in:
parent
2e4db2596a
commit
9a83706046
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user