From 5a295a1009dad3a020be10331fa8e8c6163a9106 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 1 Oct 2018 19:58:40 +0200 Subject: Scale seconds by a thousand to get milliseconds QTimeZonePrivate::dataForLocalTime()'s handling of times in a spring-forward gap added offsets in seconds to values in milliseconds. Supply the missing factor of a thousand. Change-Id: Ic32d87675f902e1c7fd85025fb70c8272a4f2db2 Reviewed-by: Thiago Macieira --- src/corelib/tools/qtimezoneprivate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp index 1a5135f103..54c2f65d94 100644 --- a/src/corelib/tools/qtimezoneprivate.cpp +++ b/src/corelib/tools/qtimezoneprivate.cpp @@ -399,7 +399,7 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs, 0 < tran.atMSecsSinceEpoch - nextTran.atMSecsSinceEpoch = (nextTran.offsetFromUtc - tran.offsetFromUtc) * 1000 */ - int dstStep = nextTran.offsetFromUtc - tran.offsetFromUtc; + int dstStep = (nextTran.offsetFromUtc - tran.offsetFromUtc) * 1000; Q_ASSERT(dstStep > 0); // How else could we get here ? if (nextFirst) { // hint thought we needed nextTran, so use tran tran.atMSecsSinceEpoch -= dstStep; @@ -439,7 +439,7 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs, // Invalid forLocalMSecs: in spring-forward gap. const int dstStep = daylightTimeOffset(early < late ? forLocalMSecs + sixteenHoursInMSecs : - forLocalMSecs - sixteenHoursInMSecs); + forLocalMSecs - sixteenHoursInMSecs) * 1000; Q_ASSERT(dstStep); // There can't be a transition without it ! utcEpochMSecs = (hint > 0) ? forStd - dstStep : forDst + dstStep; } -- cgit v1.2.3 From ced34cb3d5805f1fbaf3b275714a1a5f3585900c Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 1 Oct 2018 20:01:54 +0200 Subject: QDateTimeParser: avoid using an invalid hour by default When a time-zone does a spring-forward, skipping an hour (either to start DST or to move its standard time), there's an hour that doesn't exist on the day in question. That hour can be the first hour of the day, in which case using 0:0 as the default time is broken. So catch this case and use the first time that day that makes sense. Fixes: QTBUG-70823 Change-Id: I23dae9320a3cdd2c988841a7db1b111edb945730 Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetimeparser.cpp | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index 18c44c3a17..e6afd510fd 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -1341,12 +1341,33 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, const QDate date(year, month, day); const QTime time(hour, minute, second, msec); - return StateNode( + const QDateTime when = #if QT_CONFIG(timezone) - tspec == Qt::TimeZone ? QDateTime(date, time, timeZone) : + tspec == Qt::TimeZone ? QDateTime(date, time, timeZone) : #endif - QDateTime(date, time, tspec, zoneOffset), - state, padding, conflicts); + QDateTime(date, time, tspec, zoneOffset); + + // If hour wasn't specified, check the default we're using exists on the + // given date (which might be a spring-forward, skipping an hour). + if (parserType == QVariant::DateTime && !(isSet & HourSectionMask) && !when.isValid()) { + qint64 msecs = when.toMSecsSinceEpoch(); + // Fortunately, that gets a useful answer ... + const QDateTime replace = +#if QT_CONFIG(timezone) + tspec == Qt::TimeZone + ? QDateTime::fromMSecsSinceEpoch(msecs, timeZone) : +#endif + QDateTime::fromMSecsSinceEpoch(msecs, tspec, zoneOffset); + const QTime tick = replace.time(); + if (replace.date() == date + && (!(isSet & MinuteSection) || tick.minute() == minute) + && (!(isSet & SecondSection) || tick.second() == second) + && (!(isSet & MSecSection) || tick.msec() == msec)) { + return StateNode(replace, state, padding, conflicts); + } + } + + return StateNode(when, state, padding, conflicts); } /*! -- cgit v1.2.3