diff options
author | Edward Welbourne <edward.welbourne@qt.io> | 2016-11-03 19:00:24 +0100 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2017-11-14 17:18:21 +0000 |
commit | 948e24cb6deeaf0e55794032b90fdf20b7ef12c1 (patch) | |
tree | c611584badb1007adfa7b7dddb79264dab2cad8c | |
parent | 2b8b7a162be52f8cd6c2bc39f498a1ddfb59dd68 (diff) |
V4 Date.ParseString(): fix UTC-ness of date-only formats
ECMA-262 stipulates that date-only formats should be treated as UTC,
while date-times are handled as standard time, if no time zone is
explicitly given. Tidied up the parser a bit in the process and
documented what the spec says. Fixed some broken test-cases.
Handling of date-times without zone as local time is a correction
since edition 5.1 of ECMA-262 (which said to handle it as UTC):
http://www.ecma-international.org/ecma-262/7.0/index.html#sec-corrections-and-clarifications-in-ecmascript-2015-with-possible-compatibility-impact
We were previously handling both dates and date-times as local time,
violating the old spec for both and the revised spec for dates.
Task-number: QTBUG-56787
Change-Id: I557789d855b910ca6a859fca396af1a0205c9417
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r-- | src/qml/jsruntime/qv4dateobject.cpp | 61 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/data/assignDate.1.qml | 25 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/data/assignDate.2.qml | 17 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/data/assignDate.3.qml | 29 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/data/assignDate.4.qml | 29 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/data/assignDate.5.qml | 37 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/data/assignDate.6.qml | 33 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/data/assignDate.qml | 19 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 30 | ||||
-rw-r--r-- | tests/auto/qml/qqmlqt/tst_qqmlqt.cpp | 3 |
11 files changed, 164 insertions, 121 deletions
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index e8207bee60..3328725de4 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -378,13 +378,20 @@ static inline double TimeClip(double t) static inline double ParseString(const QString &s) { - // first try the format defined in 15.9.1.15, only if that fails fall back to - // QDateTime for parsing + /* + First, try the format defined in ECMA 262's "Date Time String Format"; + only if that fails, fall back to QDateTime for parsing - // the define string format is YYYY-MM-DDTHH:mm:ss.sssZ - // It can be date or time only, and the second and later components - // of both fields are optional - // and extended syntax for negative and large positive years exists: +/-YYYYYY + The defined string format is YYYY-MM-DDTHH:mm:ss.sssZ; the time (T and all + after it) may be omitted; in each part, the second and later components + are optional; and there's an extended syntax for negative and large + positive years: +/-YYYYYY; the leading sign, even when +, isn't optional. + If month or day is omitted, it is 01; if minute or second is omitted, it's + 00; if milliseconds are omitted, they're 000. + + When the time zone offset is absent, date-only forms are interpreted as + indicating a UTC time and date-time forms are interpreted in local time. + */ enum Format { Year, @@ -417,6 +424,8 @@ static inline double ParseString(const QString &s) int msec = 0; int offsetSign = 1; int offset = 0; + bool seenT = false; + bool seenZ = false; // Have seen zone, i.e. +HH:mm or literal Z. bool error = false; if (*ch == '+' || *ch == '-') { @@ -425,7 +434,7 @@ static inline double ParseString(const QString &s) yearSign = -1; ++ch; } - while (ch <= end) { + for (; ch <= end && !error && format != Done; ++ch) { if (*ch >= '0' && *ch <= '9') { current *= 10; current += ch->unicode() - '0'; @@ -453,7 +462,7 @@ static inline double ParseString(const QString &s) break; case Minute: minute = current; - error = (currentSize != 2) || minute > 60; + error = (currentSize != 2) || minute >= 60; break; case Second: second = current; @@ -464,8 +473,10 @@ static inline double ParseString(const QString &s) error = (currentSize != 3); break; case TimezoneHour: - offset = current*60; - error = (currentSize != 2) || offset > 23*60; + Q_ASSERT(offset == 0 && !seenZ); + offset = current * 60; + error = (currentSize != 2) || current > 23; + seenZ = true; break; case TimezoneMinute: offset += current; @@ -476,6 +487,7 @@ static inline double ParseString(const QString &s) if (format >= Hour) error = true; format = Hour; + seenT = true; } else if (*ch == '-') { if (format < Day) ++format; @@ -484,6 +496,7 @@ static inline double ParseString(const QString &s) else if (format >= TimezoneHour) error = true; else { + Q_ASSERT(offset == 0 && !seenZ); offsetSign = -1; format = TimezoneHour; } @@ -496,23 +509,31 @@ static inline double ParseString(const QString &s) error = true; ++format; } else if (*ch == '+') { - if (format < Minute || format >= TimezoneHour) + if (seenZ || format < Minute || format >= TimezoneHour) error = true; format = TimezoneHour; - } else if (*ch == 'Z' || ch->unicode() == 0) { + } else if (*ch == 'Z') { + if (seenZ || format < Minute || format >= TimezoneHour) + error = true; + else + Q_ASSERT(offset == 0); + format = Done; + seenZ = true; + } else if (ch->unicode() == 0) { format = Done; } current = 0; currentSize = 0; } - if (error || format == Done) - break; - ++ch; } if (!error) { double t = MakeDate(MakeDay(year * yearSign, month, day), MakeTime(hour, minute, second, msec)); - t -= offset * offsetSign * 60 * 1000; + if (seenZ) + t -= offset * offsetSign * 60 * 1000; + else if (seenT) // No zone specified, treat date-time as local time + t = UTC(t); + // else: treat plain date as already in UTC return t; } @@ -571,7 +592,11 @@ static inline double ParseString(const QString &s) << QStringLiteral("d MMMM, yyyy hh:mm:ss"); for (int i = 0; i < formats.size(); ++i) { - dt = QDateTime::fromString(s, formats.at(i)); + const QString &format(formats.at(i)); + dt = format.indexOf(QLatin1String("hh:mm")) < 0 + ? QDateTime(QDate::fromString(s, format), + QTime(0, 0, 0), Qt::UTC) + : QDateTime::fromString(s, format); // as local time if (dt.isValid()) break; } @@ -591,7 +616,7 @@ static inline QDateTime ToDateTime(double t, Qt::TimeSpec spec) { if (std::isnan(t)) return QDateTime(); - return QDateTime::fromMSecsSinceEpoch(t, spec); + return QDateTime::fromMSecsSinceEpoch(t, Qt::UTC).toTimeSpec(spec); } static inline QString ToString(double t) diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index b5edad69ae..78cc95b98d 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1370,7 +1370,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant) case QMetaType::QDateTime: return QV4::Encode(newDateObject(*reinterpret_cast<const QDateTime *>(ptr))); case QMetaType::QDate: - return QV4::Encode(newDateObject(QDateTime(*reinterpret_cast<const QDate *>(ptr)))); + return QV4::Encode(newDateObject(QDateTime(*reinterpret_cast<const QDate *>(ptr), QTime(0, 0, 0), Qt::UTC))); case QMetaType::QTime: return QV4::Encode(newDateObjectFromTime(*reinterpret_cast<const QTime *>(ptr))); case QMetaType::QRegExp: diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.1.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.1.qml index efca6cdb80..8912d2a314 100644 --- a/tests/auto/qml/qqmlecmascript/data/assignDate.1.qml +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.1.qml @@ -11,25 +11,26 @@ MyTypeObject { dateTimeProperty = dateTimeVar dateTimeProperty2 = dateTimeVar2 - // Commented properties do not currently test true: - boolProperty = //(dateProperty.getTime() == dateVar.getTime()) && + boolProperty = (dateProperty.getTime() == dateVar.getTime()) && (dateProperty.getFullYear() == 2009) && (dateProperty.getMonth() == 5-1) && - //(dateProperty.getDate() == 12) && - (dateProperty.getHours() == 0) && + (dateProperty.getUTCDate() == 12) && + (dateProperty.getUTCHours() == 0) && + (dateProperty.getUTCMinutes() == 0) && + (dateProperty.getUTCSeconds() == 0) && (dateTimeProperty.getTime() == dateTimeVar.getTime()) && (dateTimeProperty.getFullYear() == 2009) && (dateTimeProperty.getMonth() == 5-1) && - //(dateTimeProperty.getDate() == 12) && - //(dateTimeProperty.getHours() == 0) && - (dateTimeProperty.getMinutes() == 0) && - (dateTimeProperty.getSeconds() == 1) && + (dateTimeProperty.getUTCDate() == 12) && + (dateTimeProperty.getUTCHours() == 0) && + (dateTimeProperty.getUTCMinutes() == 0) && + (dateTimeProperty.getUTCSeconds() == 1) && (dateTimeProperty2.getTime() == dateTimeVar2.getTime()) && (dateTimeProperty2.getFullYear() == 2009) && (dateTimeProperty2.getMonth() == 5-1) && - //(dateTimeProperty2.getDate() == 12) && - //(dateTimeProperty2.getHours() == 23) && - (dateTimeProperty2.getMinutes() == 59) && - (dateTimeProperty2.getSeconds() == 59) + (dateTimeProperty2.getUTCDate() == 12) && + (dateTimeProperty2.getUTCHours() == 23) && + (dateTimeProperty2.getUTCMinutes() == 59) && + (dateTimeProperty2.getUTCSeconds() == 59) } } diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.2.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.2.qml index 71dd188f05..f8c1f6eb8f 100644 --- a/tests/auto/qml/qqmlecmascript/data/assignDate.2.qml +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.2.qml @@ -12,24 +12,25 @@ MyTypeObject { var dateTimeVar = new Date("2009-05-12T00:00:01") var dateTimeVar2 = new Date("2009-05-12T23:59:59") - // Commented properties do not currently test true: - boolProperty = //(dateProperty.getTime() == dateVar.getTime()) && + boolProperty = (dateProperty.getTime() == dateVar.getTime()) && (dateProperty.getFullYear() == 2009) && (dateProperty.getMonth() == 5-1) && - //(dateProperty.getDate() == 12) && - (dateProperty.getHours() == 0) && + (dateProperty.getUTCDate() == 12) && + (dateProperty.getUTCHours() == 0) && + (dateProperty.getUTCMinutes() == 0) && + (dateProperty.getUTCSeconds() == 0) && (dateTimeProperty.getTime() == dateTimeVar.getTime()) && (dateTimeProperty.getFullYear() == 2009) && (dateTimeProperty.getMonth() == 5-1) && - //(dateTimeProperty.getDate() == 12) && - //(dateTimeProperty.getHours() == 0) && + (dateTimeProperty.getDate() == 12) && + (dateTimeProperty.getHours() == 0) && (dateTimeProperty.getMinutes() == 0) && (dateTimeProperty.getSeconds() == 1) && (dateTimeProperty2.getTime() == dateTimeVar2.getTime()) && (dateTimeProperty2.getFullYear() == 2009) && (dateTimeProperty2.getMonth() == 5-1) && - //(dateTimeProperty2.getDate() == 12) && - //(dateTimeProperty2.getHours() == 23) && + (dateTimeProperty2.getDate() == 12) && + (dateTimeProperty2.getHours() == 23) && (dateTimeProperty2.getMinutes() == 59) && (dateTimeProperty2.getSeconds() == 59) } diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.3.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.3.qml index 2cf740645c..e960eef193 100644 --- a/tests/auto/qml/qqmlecmascript/data/assignDate.3.qml +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.3.qml @@ -2,35 +2,36 @@ import Qt.test 1.0 import QtQuick 2.0 MyTypeObject { - dateProperty: if (1) "2009-05-12Z" + dateProperty: if (1) "2009-05-12" dateTimeProperty: if (1) "2009-05-12T00:00:01Z" dateTimeProperty2: if (1) "2009-05-12T23:59:59Z" boolProperty: false Component.onCompleted: { - var dateVar = new Date("2009-05-12Z") + var dateVar = new Date("2009-05-12") var dateTimeVar = new Date("2009-05-12T00:00:01Z") var dateTimeVar2 = new Date("2009-05-12T23:59:59Z") - // Commented properties do not currently test true: - boolProperty = //(dateProperty.getTime() == dateVar.getTime()) && + boolProperty = (dateProperty.getTime() == dateVar.getTime()) && (dateProperty.getFullYear() == 2009) && (dateProperty.getMonth() == 5-1) && - //(dateProperty.getDate() == 12) && - (dateProperty.getHours() == 0) && + (dateProperty.getUTCDate() == 12) && + (dateProperty.getUTCHours() == 0) && + (dateProperty.getUTCMinutes() == 0) && + (dateProperty.getUTCSeconds() == 0) && (dateTimeProperty.getTime() == dateTimeVar.getTime()) && (dateTimeProperty.getFullYear() == 2009) && (dateTimeProperty.getMonth() == 5-1) && - //(dateTimeProperty.getDate() == 12) && - //(dateTimeProperty.getHours() == 0) && - (dateTimeProperty.getMinutes() == 0) && - (dateTimeProperty.getSeconds() == 1) && + (dateTimeProperty.getUTCDate() == 12) && + (dateTimeProperty.getUTCHours() == 0) && + (dateTimeProperty.getUTCMinutes() == 0) && + (dateTimeProperty.getUTCSeconds() == 1) && (dateTimeProperty2.getTime() == dateTimeVar2.getTime()) && (dateTimeProperty2.getFullYear() == 2009) && (dateTimeProperty2.getMonth() == 5-1) && - //(dateTimeProperty2.getDate() == 12) && - //(dateTimeProperty2.getHours() == 23) && - (dateTimeProperty2.getMinutes() == 59) && - (dateTimeProperty2.getSeconds() == 59) + (dateTimeProperty2.getUTCDate() == 12) && + (dateTimeProperty2.getUTCHours() == 23) && + (dateTimeProperty2.getUTCMinutes() == 59) && + (dateTimeProperty2.getUTCSeconds() == 59) } } diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.4.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.4.qml index 9b4975c833..6dd29afbc9 100644 --- a/tests/auto/qml/qqmlecmascript/data/assignDate.4.qml +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.4.qml @@ -2,35 +2,36 @@ import Qt.test 1.0 import QtQuick 2.0 MyTypeObject { - dateProperty: if (1) new Date("2009-05-12Z") + dateProperty: if (1) new Date("2009-05-12") dateTimeProperty: if (1) new Date("2009-05-12T00:00:01Z") dateTimeProperty2: if (1) new Date("2009-05-12T23:59:59Z") boolProperty: false Component.onCompleted: { - var dateVar = new Date("2009-05-12Z") + var dateVar = new Date("2009-05-12") var dateTimeVar = new Date("2009-05-12T00:00:01Z") var dateTimeVar2 = new Date("2009-05-12T23:59:59Z") - // Commented properties do not currently test true: - boolProperty = //(dateProperty.getTime() == dateVar.getTime()) && + boolProperty = (dateProperty.getTime() == dateVar.getTime()) && (dateProperty.getFullYear() == 2009) && (dateProperty.getMonth() == 5-1) && - //(dateProperty.getDate() == 12) && - (dateProperty.getHours() == 0) && + (dateProperty.getUTCDate() == 12) && + (dateProperty.getUTCHours() == 0) && + (dateProperty.getUTCMinutes() == 0) && + (dateProperty.getUTCSeconds() == 0) && (dateTimeProperty.getTime() == dateTimeVar.getTime()) && (dateTimeProperty.getFullYear() == 2009) && (dateTimeProperty.getMonth() == 5-1) && - //(dateTimeProperty.getDate() == 12) && - //(dateTimeProperty.getHours() == 0) && - (dateTimeProperty.getMinutes() == 0) && - (dateTimeProperty.getSeconds() == 1) && + (dateTimeProperty.getUTCDate() == 12) && + (dateTimeProperty.getUTCHours() == 0) && + (dateTimeProperty.getUTCMinutes() == 0) && + (dateTimeProperty.getUTCSeconds() == 1) && (dateTimeProperty2.getTime() == dateTimeVar2.getTime()) && (dateTimeProperty2.getFullYear() == 2009) && (dateTimeProperty2.getMonth() == 5-1) && - //(dateTimeProperty2.getDate() == 12) && - //(dateTimeProperty2.getHours() == 23) && - (dateTimeProperty2.getMinutes() == 59) && - (dateTimeProperty2.getSeconds() == 59) + (dateTimeProperty2.getUTCDate() == 12) && + (dateTimeProperty2.getUTCHours() == 23) && + (dateTimeProperty2.getUTCMinutes() == 59) && + (dateTimeProperty2.getUTCSeconds() == 59) } } diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.5.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.5.qml index 2cf740645c..cfadaafc54 100644 --- a/tests/auto/qml/qqmlecmascript/data/assignDate.5.qml +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.5.qml @@ -2,35 +2,36 @@ import Qt.test 1.0 import QtQuick 2.0 MyTypeObject { - dateProperty: if (1) "2009-05-12Z" - dateTimeProperty: if (1) "2009-05-12T00:00:01Z" - dateTimeProperty2: if (1) "2009-05-12T23:59:59Z" + dateProperty: if (1) "2009-05-12" + dateTimeProperty: if (1) "2009-05-12T00:00:01+02:00" + dateTimeProperty2: if (1) "2009-05-12T23:59:59+02:00" boolProperty: false Component.onCompleted: { - var dateVar = new Date("2009-05-12Z") - var dateTimeVar = new Date("2009-05-12T00:00:01Z") - var dateTimeVar2 = new Date("2009-05-12T23:59:59Z") + var dateVar = new Date("2009-05-12") + var dateTimeVar = new Date("2009-05-12T00:00:01+02:00") + var dateTimeVar2 = new Date("2009-05-12T23:59:59+02:00") - // Commented properties do not currently test true: - boolProperty = //(dateProperty.getTime() == dateVar.getTime()) && + boolProperty = (dateProperty.getTime() == dateVar.getTime()) && (dateProperty.getFullYear() == 2009) && (dateProperty.getMonth() == 5-1) && - //(dateProperty.getDate() == 12) && - (dateProperty.getHours() == 0) && + (dateProperty.getUTCDate() == 12) && + (dateProperty.getUTCHours() == 0) && + (dateProperty.getUTCMinutes() == 0) && + (dateProperty.getUTCSeconds() == 0) && (dateTimeProperty.getTime() == dateTimeVar.getTime()) && (dateTimeProperty.getFullYear() == 2009) && (dateTimeProperty.getMonth() == 5-1) && - //(dateTimeProperty.getDate() == 12) && - //(dateTimeProperty.getHours() == 0) && - (dateTimeProperty.getMinutes() == 0) && - (dateTimeProperty.getSeconds() == 1) && + (dateTimeProperty.getUTCDate() == 11) && + (dateTimeProperty.getUTCHours() == 22) && + (dateTimeProperty.getUTCMinutes() == 0) && + (dateTimeProperty.getUTCSeconds() == 1) && (dateTimeProperty2.getTime() == dateTimeVar2.getTime()) && (dateTimeProperty2.getFullYear() == 2009) && (dateTimeProperty2.getMonth() == 5-1) && - //(dateTimeProperty2.getDate() == 12) && - //(dateTimeProperty2.getHours() == 23) && - (dateTimeProperty2.getMinutes() == 59) && - (dateTimeProperty2.getSeconds() == 59) + (dateTimeProperty2.getUTCDate() == 12) && + (dateTimeProperty2.getUTCHours() == 21) && + (dateTimeProperty2.getUTCMinutes() == 59) && + (dateTimeProperty2.getUTCSeconds() == 59) } } diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.6.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.6.qml index 73e26db0c8..97cd0d1e60 100644 --- a/tests/auto/qml/qqmlecmascript/data/assignDate.6.qml +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.6.qml @@ -3,34 +3,35 @@ import QtQuick 2.0 MyTypeObject { dateProperty: if (1) new Date("2009-05-12") - dateTimeProperty: if (1) new Date("2009-05-12T02:00:01+02:00") - dateTimeProperty2: if (1) new Date("2009-05-13T01:59:59+02:00") + dateTimeProperty: if (1) new Date("2009-05-12T00:00:01+02:00") + dateTimeProperty2: if (1) new Date("2009-05-12T23:59:59+02:00") boolProperty: false Component.onCompleted: { var dateVar = new Date("2009-05-12") - var dateTimeVar = new Date("2009-05-12T02:00:01+02:00") - var dateTimeVar2 = new Date("2009-05-13T01:59:59+02:00") + var dateTimeVar = new Date("2009-05-12T00:00:01+02:00") + var dateTimeVar2 = new Date("2009-05-12T23:59:59+02:00") - // Commented properties do not currently test true: - boolProperty = //(dateProperty.getTime() == dateVar.getTime()) && + boolProperty = (dateProperty.getTime() == dateVar.getTime()) && (dateProperty.getFullYear() == 2009) && (dateProperty.getMonth() == 5-1) && - //(dateProperty.getDate() == 12) && - (dateProperty.getHours() == 0) && + (dateProperty.getUTCDate() == 12) && + (dateProperty.getUTCHours() == 0) && + (dateProperty.getUTCMinutes() == 0) && + (dateProperty.getUTCSeconds() == 0) && (dateTimeProperty.getTime() == dateTimeVar.getTime()) && (dateTimeProperty.getFullYear() == 2009) && (dateTimeProperty.getMonth() == 5-1) && - //(dateTimeProperty.getDate() == 12) && - //(dateTimeProperty.getHours() == 0) && - (dateTimeProperty.getMinutes() == 0) && - (dateTimeProperty.getSeconds() == 1) && + (dateTimeProperty.getUTCDate() == 11) && + (dateTimeProperty.getUTCHours() == 22) && + (dateTimeProperty.getUTCMinutes() == 0) && + (dateTimeProperty.getUTCSeconds() == 1) && (dateTimeProperty2.getTime() == dateTimeVar2.getTime()) && (dateTimeProperty2.getFullYear() == 2009) && (dateTimeProperty2.getMonth() == 5-1) && - //(dateTimeProperty2.getDate() == 12) && - //(dateTimeProperty2.getHours() == 23) && - (dateTimeProperty2.getMinutes() == 59) && - (dateTimeProperty2.getSeconds() == 59) + (dateTimeProperty2.getUTCDate() == 12) && + (dateTimeProperty2.getUTCHours() == 21) && + (dateTimeProperty2.getUTCMinutes() == 59) && + (dateTimeProperty2.getUTCSeconds() == 59) } } diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.qml index 14fe20787b..73677e99f1 100644 --- a/tests/auto/qml/qqmlecmascript/data/assignDate.qml +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.qml @@ -7,28 +7,31 @@ MyTypeObject { var dateTimeVar = new Date("2009-05-12T00:00:01") var dateTimeVar2 = new Date("2009-05-12T23:59:59") + // Date, with no zone specified, is implicitly UTC dateProperty = dateVar + // Date-time, with no zone, is implicitly local-time dateTimeProperty = dateTimeVar dateTimeProperty2 = dateTimeVar2 - // Commented properties do not currently test true: - boolProperty = //(dateProperty.getTime() == dateVar.getTime()) && + boolProperty = (dateProperty.getTime() == dateVar.getTime()) && (dateProperty.getFullYear() == 2009) && (dateProperty.getMonth() == 5-1) && - //(dateProperty.getDate() == 12) && - (dateProperty.getHours() == 0) && + (dateProperty.getDate() == 12) && + (dateProperty.getUTCHours() == 0) && + (dateProperty.getUTCMinutes() == 0) && + (dateProperty.getUTCSeconds() == 0) && (dateTimeProperty.getTime() == dateTimeVar.getTime()) && (dateTimeProperty.getFullYear() == 2009) && (dateTimeProperty.getMonth() == 5-1) && - //(dateTimeProperty.getDate() == 12) && - //(dateTimeProperty.getHours() == 0) && + (dateTimeProperty.getDate() == 12) && + (dateTimeProperty.getHours() == 0) && (dateTimeProperty.getMinutes() == 0) && (dateTimeProperty.getSeconds() == 1) && (dateTimeProperty2.getTime() == dateTimeVar2.getTime()) && (dateTimeProperty2.getFullYear() == 2009) && (dateTimeProperty2.getMonth() == 5-1) && - //(dateTimeProperty2.getDate() == 12) && - //(dateTimeProperty2.getHours() == 23) && + (dateTimeProperty2.getDate() == 12) && + (dateTimeProperty2.getHours() == 23) && (dateTimeProperty2.getMinutes() == 59) && (dateTimeProperty2.getSeconds() == 59) } diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 35f1534478..19c12ead1c 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -443,29 +443,37 @@ void tst_qqmlecmascript::assignBasicTypes() void tst_qqmlecmascript::assignDate_data() { QTest::addColumn<QUrl>("source"); + QTest::addColumn<int>("timeOffset"); // -1 for local-time, else minutes from UTC - QTest::newRow("Component.onComplete JS Parse") << testFileUrl("assignDate.qml"); - QTest::newRow("Component.onComplete JS") << testFileUrl("assignDate.1.qml"); - QTest::newRow("Binding JS") << testFileUrl("assignDate.2.qml"); - QTest::newRow("Binding UTC") << testFileUrl("assignDate.3.qml"); - QTest::newRow("Binding JS UTC") << testFileUrl("assignDate.4.qml"); - QTest::newRow("Binding UTC+2") << testFileUrl("assignDate.5.qml"); - QTest::newRow("Binding JS UTC+2 ") << testFileUrl("assignDate.6.qml"); + QTest::newRow("Component.onComplete JS Parse") << testFileUrl("assignDate.qml") << -1; + QTest::newRow("Component.onComplete JS") << testFileUrl("assignDate.1.qml") << 0; + QTest::newRow("Binding JS") << testFileUrl("assignDate.2.qml") << -1; + QTest::newRow("Binding UTC") << testFileUrl("assignDate.3.qml") << 0; + QTest::newRow("Binding JS UTC") << testFileUrl("assignDate.4.qml") << 0; + QTest::newRow("Binding UTC+2") << testFileUrl("assignDate.5.qml") << 120; + QTest::newRow("Binding JS UTC+2 ") << testFileUrl("assignDate.6.qml") << 120; } void tst_qqmlecmascript::assignDate() { QFETCH(QUrl, source); + QFETCH(int, timeOffset); QQmlComponent component(&engine, source); QScopedPointer<QObject> obj(component.create()); MyTypeObject *object = qobject_cast<MyTypeObject *>(obj.data()); QVERIFY(object != 0); - // Dates received from JS are automatically converted to local time - QDate expectedDate(QDateTime(QDate(2009, 5, 12), QTime(0, 0, 0), Qt::UTC).toLocalTime().date()); - QDateTime expectedDateTime(QDateTime(QDate(2009, 5, 12), QTime(0, 0, 1), Qt::UTC).toLocalTime()); - QDateTime expectedDateTime2(QDateTime(QDate(2009, 5, 12), QTime(23, 59, 59), Qt::UTC).toLocalTime()); + QDate expectedDate(2009, 5, 12); + QDateTime expectedDateTime; + QDateTime expectedDateTime2; + if (timeOffset == -1) { + expectedDateTime = QDateTime(QDate(2009, 5, 12), QTime(0, 0, 1), Qt::LocalTime); + expectedDateTime2 = QDateTime(QDate(2009, 5, 12), QTime(23, 59, 59), Qt::LocalTime); + } else { + expectedDateTime = QDateTime(QDate(2009, 5, 12), QTime(0, 0, 1), Qt::OffsetFromUTC, timeOffset * 60); + expectedDateTime2 = QDateTime(QDate(2009, 5, 12), QTime(23, 59, 59), Qt::OffsetFromUTC, timeOffset * 60); + } QCOMPARE(object->dateProperty(), expectedDate); QCOMPARE(object->dateTimeProperty(), expectedDateTime); diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp index 0576650d01..6c920471c4 100644 --- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp +++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp @@ -888,7 +888,8 @@ void tst_qqmlqt::dateTimeFormattingVariants_data() QTest::newRow("formatTime, qtime") << "formatTime" << QVariant::fromValue(time) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz")); QDate date(2011,5,31); - temporary = QDateTime(date); + // V4 reads the date in UTC but DateObject::toQDateTime() gives it back in local time: + temporary = QDateTime(date, QTime(0, 0, 0), Qt::UTC).toLocalTime(); QTest::newRow("formatDate, qdate") << "formatDate" << QVariant::fromValue(date) << (QStringList() << temporary.date().toString(Qt::DefaultLocaleShortDate) << temporary.date().toString(Qt::DefaultLocaleLongDate) << temporary.date().toString("ddd MMMM d yy")); QTest::newRow("formatDateTime, qdate") << "formatDateTime" << QVariant::fromValue(date) << (QStringList() << temporary.toString(Qt::DefaultLocaleShortDate) << temporary.toString(Qt::DefaultLocaleLongDate) << temporary.toString("M/d/yy H:m:s a")); QTest::newRow("formatTime, qdate") << "formatTime" << QVariant::fromValue(date) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz")); |