summaryrefslogtreecommitdiffstats
path: root/src/widgets/widgets/qdatetimeedit.cpp
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2020-02-20 17:30:57 +0100
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2020-02-27 19:35:28 +0100
commit924b97d6abf6f9935c9698984a1596c65324e3fa (patch)
treea0726e4c0e18bdb133dd0d09734c27f94e2d0bb8 /src/widgets/widgets/qdatetimeedit.cpp
parent31b06a0437f96935f12eb0db003a5867c83a9228 (diff)
Fix QDateTimeEdit's handling of invalid time in dst gap
During a spring forward, a time-zone omits an hour. A QDateTime with such an hour is invalid, but QDateTimeEdit's handling of this invalid time was not done correctly. With this fix, up/down changes of any field that would result in an invalid date-time corrects the time to be valid, while leaving as much as possible of the user-entered data unchanged. To do that, we rely on QDateTime::toMSecsSinceEpoch to return a value even for such an invalid time, which then can be used to construct a valid QDateTime. Edits that would result in an invalid hour are reverted to the previous when pressing return, if correctionMode is CorrectToPreviousValue. This change also implements support for CorrectToNearestValue, which uses the same mechanism as when stepping over an invalid time. Include a test that verifies that the various interactions result in a reasonable value. Since QDateTimeEdit does not respect the timezone or timespec of the QDateTime it is initialized with, we have to find the first hour of daylight saving time for a year that we know works for most time zones. Failing that, we have to skip the tests. Verified in a wide range of time zones. Change-Id: I05b906ae3b5f6681891d23704f00f9c10cd479ae Fixes: QTBUG-79803 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/widgets/widgets/qdatetimeedit.cpp')
-rw-r--r--src/widgets/widgets/qdatetimeedit.cpp22
1 files changed, 21 insertions, 1 deletions
diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp
index 63d5ae268e..c89cef99b5 100644
--- a/src/widgets/widgets/qdatetimeedit.cpp
+++ b/src/widgets/widgets/qdatetimeedit.cpp
@@ -1442,7 +1442,16 @@ void QDateTimeEdit::fixup(QString &input) const
QValidator::State state;
int copy = d->edit->cursorPosition();
- d->validateAndInterpret(input, copy, state, true);
+ QDateTime value = d->validateAndInterpret(input, copy, state, true);
+ /*
+ String was valid, but the datetime still is not; use the time that
+ has the same distance from epoch.
+ CorrectToPreviousValue correction is handled by QAbstractSpinBox.
+ */
+ if (!value.isValid() && d->correctionMode == QAbstractSpinBox::CorrectToNearestValue) {
+ value = QDateTime::fromMSecsSinceEpoch(value.toMSecsSinceEpoch(), value.timeSpec());
+ input = textFromDateTime(value);
+ }
}
@@ -2060,6 +2069,17 @@ QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) c
const int oldDay = v.date().day(calendar);
setDigit(v, sectionIndex, val);
+ /*
+ Stepping into a daylight saving time that doesn't exist,
+ so use the time that has the same distance from epoch.
+ */
+ if (!v.isValid()) {
+ auto msecsSinceEpoch = v.toMSecsSinceEpoch();
+ // decreasing from e.g 3am to 2am would get us back to 3am, but we want 1am
+ if (steps < 0 && sn.type & HourSectionMask)
+ msecsSinceEpoch -= 3600 * 1000;
+ v = QDateTime::fromMSecsSinceEpoch(msecsSinceEpoch, v.timeSpec());
+ }
// if this sets year or month it will make
// sure that days are lowered if needed.