aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp25
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDate-October.qml12
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDate-denormal-Feb.qml11
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDate-denormal-March.qml11
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDate-denormal-leap.qml11
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDate-denormal-wrap.qml11
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDate-denormal-year.qml11
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDateTime-October.qml16
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-March.qml15
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-hours.qml15
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-leap.qml15
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-minutes.qml15
-rw-r--r--tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-seconds.qml15
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp80
14 files changed, 258 insertions, 5 deletions
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 21c6a5d06b..e313ebe300 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -296,13 +296,28 @@ static double MakeDay(double year, double month, double day)
if (month < 0)
month += 12.0;
- double d = DayFromYear(year);
- bool leap = InLeapYear(d*msPerDay);
+ /* Quoting the spec:
- d += DayFromMonth(month, leap);
- d += day - 1;
+ Find a value t such that YearFromTime(t) is ym and MonthFromTime(t) is mn
+ and DateFromTime(t) is 1; but if this is not possible (because some
+ argument is out of range), return NaN.
+ */
+ double first = DayFromYear(year);
+ /* Beware floating-point glitches: don't test the first millisecond of a
+ * year, month or day when we could test a moment firmly in the interior of
+ * the interval. A rounding glitch might give the first millisecond to the
+ * preceding interval.
+ */
+ bool leap = InLeapYear((first + 60) * msPerDay);
- return d;
+ first += DayFromMonth(month, leap);
+ const double t = first * msPerDay + msPerDay / 2; // Noon on the first of the month
+ Q_ASSERT(Day(t) == first);
+ if (YearFromTime(t) != year || MonthFromTime(t) != month || DateFromTime(t) != 1) {
+ qWarning("Apparently out-of-range date %.0f-%02.0f-%02.0f", year, month, day);
+ return qt_qnan();
+ }
+ return first + day - 1;
}
static inline double MakeDate(double day, double time)
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-October.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-October.qml
new file mode 100644
index 0000000000..6686831e1c
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDate-October.qml
@@ -0,0 +1,12 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ // QTBUG-78996
+ dateProperty = new Date(2019, 9, 3)
+ boolProperty = (dateProperty.getFullYear() == 2019
+ && dateProperty.getMonth() == 9
+ && dateProperty.getDate() == 3)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-Feb.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-Feb.qml
new file mode 100644
index 0000000000..29ec40ffbd
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-Feb.qml
@@ -0,0 +1,11 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateProperty = new Date(2019, 2, 0) // Feb 28th
+ boolProperty = (dateProperty.getFullYear() == 2019
+ && dateProperty.getMonth() == 1
+ && dateProperty.getDate() == 28)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-March.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-March.qml
new file mode 100644
index 0000000000..7fc8bf43bd
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-March.qml
@@ -0,0 +1,11 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateProperty = new Date(2019, 1, 29) // March 1st
+ boolProperty = (dateProperty.getFullYear() == 2019
+ && dateProperty.getMonth() == 2
+ && dateProperty.getDate() == 1)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-leap.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-leap.qml
new file mode 100644
index 0000000000..6dd84810e6
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-leap.qml
@@ -0,0 +1,11 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateProperty = new Date(2020, 2, 0) // Feb 29th
+ boolProperty = (dateProperty.getFullYear() == 2020
+ && dateProperty.getMonth() == 1
+ && dateProperty.getDate() == 29)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-wrap.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-wrap.qml
new file mode 100644
index 0000000000..ddb79727ef
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-wrap.qml
@@ -0,0 +1,11 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateProperty = new Date(2017, 40, -61) // 2020, Feb 29th
+ boolProperty = (dateProperty.getFullYear() == 2020
+ && dateProperty.getMonth() == 1
+ && dateProperty.getDate() == 29)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-year.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-year.qml
new file mode 100644
index 0000000000..90514c39c8
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-year.qml
@@ -0,0 +1,11 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateProperty = new Date(2019, 12, 0) // Dec 31
+ boolProperty = (dateProperty.getFullYear() == 2019
+ && dateProperty.getMonth() == 11
+ && dateProperty.getDate() == 31)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-October.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-October.qml
new file mode 100644
index 0000000000..c97076f887
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-October.qml
@@ -0,0 +1,16 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ // QTBUG-78996
+ dateTimeProperty = new Date(2019, 9, 3, 12)
+ boolProperty = (dateTimeProperty.getFullYear() == 2019
+ && dateTimeProperty.getMonth() == 9
+ && dateTimeProperty.getDate() == 3
+ && dateTimeProperty.getHours() == 12
+ && dateTimeProperty.getMinutes() == 0
+ && dateTimeProperty.getSeconds() == 0
+ && dateTimeProperty.getMilliseconds() == 0)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-March.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-March.qml
new file mode 100644
index 0000000000..2b6b9af3e1
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-March.qml
@@ -0,0 +1,15 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateTimeProperty = new Date(2019, 1, 28, 23, 59, 59, 1001) // 2019-3-1 0:0:0.001
+ boolProperty = (dateTimeProperty.getFullYear() == 2019
+ && dateTimeProperty.getMonth() == 2
+ && dateTimeProperty.getDate() == 1
+ && dateTimeProperty.getHours() == 0
+ && dateTimeProperty.getMinutes() == 0
+ && dateTimeProperty.getSeconds() == 0
+ && dateTimeProperty.getMilliseconds() == 1)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-hours.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-hours.qml
new file mode 100644
index 0000000000..7d018e2904
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-hours.qml
@@ -0,0 +1,15 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateTimeProperty = new Date(2019, 11, 31, 1440) // 2020-2-29 0:0:0
+ boolProperty = (dateTimeProperty.getFullYear() == 2020
+ && dateTimeProperty.getMonth() == 1
+ && dateTimeProperty.getDate() == 29
+ && dateTimeProperty.getHours() == 0
+ && dateTimeProperty.getMinutes() == 0
+ && dateTimeProperty.getSeconds() == 0
+ && dateTimeProperty.getMilliseconds() == 0)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-leap.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-leap.qml
new file mode 100644
index 0000000000..0a7687c669
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-leap.qml
@@ -0,0 +1,15 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateTimeProperty = new Date(2020, 2, 1, 0, 0, 0, -1) // 2020-2-29 23:59:59.999
+ boolProperty = (dateTimeProperty.getFullYear() == 2020
+ && dateTimeProperty.getMonth() == 1
+ && dateTimeProperty.getDate() == 29
+ && dateTimeProperty.getHours() == 23
+ && dateTimeProperty.getMinutes() == 59
+ && dateTimeProperty.getSeconds() == 59
+ && dateTimeProperty.getMilliseconds() == 999)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-minutes.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-minutes.qml
new file mode 100644
index 0000000000..738d603b4b
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-minutes.qml
@@ -0,0 +1,15 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateTimeProperty = new Date(2020, 1, 28, 0, 1440) // 2020-2-29 0:0:0
+ boolProperty = (dateTimeProperty.getFullYear() == 2020
+ && dateTimeProperty.getMonth() == 1
+ && dateTimeProperty.getDate() == 29
+ && dateTimeProperty.getHours() == 0
+ && dateTimeProperty.getMinutes() == 0
+ && dateTimeProperty.getSeconds() == 0
+ && dateTimeProperty.getMilliseconds() == 0)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-seconds.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-seconds.qml
new file mode 100644
index 0000000000..d48534f0d0
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-seconds.qml
@@ -0,0 +1,15 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyTypeObject {
+ Component.onCompleted: {
+ dateTimeProperty = new Date(2020, 1, 28, 23, 0, 3600) // 2020-2-29 0:0:0
+ boolProperty = (dateTimeProperty.getFullYear() == 2020
+ && dateTimeProperty.getMonth() == 1
+ && dateTimeProperty.getDate() == 29
+ && dateTimeProperty.getHours() == 0
+ && dateTimeProperty.getMinutes() == 0
+ && dateTimeProperty.getSeconds() == 0
+ && dateTimeProperty.getMilliseconds() == 0)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index df4963cb6e..7a9c611269 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -78,6 +78,10 @@ private slots:
void assignDate();
void exportDate_data();
void exportDate();
+ void checkDate_data();
+ void checkDate();
+ void checkDateTime_data();
+ void checkDateTime();
void idShortcutInvalidates();
void boolPropertiesEvaluateAsBool();
void methods();
@@ -565,6 +569,82 @@ void tst_qqmlecmascript::exportDate()
QCOMPARE(object->boolProperty(), true);
}
+void tst_qqmlecmascript::checkDate_data()
+{
+ QTest::addColumn<QUrl>("source");
+ QTest::addColumn<QDate>("date");
+ // NB: JavaScript month-indices are Jan = 0 to Dec = 11; QDate's are Jan = 1 to Dec = 12.
+ QTest::newRow("denormal-March")
+ << testFileUrl("checkDate-denormal-March.qml")
+ << QDate(2019, 3, 1);
+ QTest::newRow("denormal-leap")
+ << testFileUrl("checkDate-denormal-leap.qml")
+ << QDate(2020, 2, 29);
+ QTest::newRow("denormal-Feb")
+ << testFileUrl("checkDate-denormal-Feb.qml")
+ << QDate(2019, 2, 28);
+ QTest::newRow("denormal-year")
+ << testFileUrl("checkDate-denormal-year.qml")
+ << QDate(2019, 12, 31);
+ QTest::newRow("denormal-wrap")
+ << testFileUrl("checkDate-denormal-wrap.qml")
+ << QDate(2020, 2, 29);
+ QTest::newRow("October")
+ << testFileUrl("checkDate-October.qml")
+ << QDate(2019, 10, 3);
+}
+
+void tst_qqmlecmascript::checkDate()
+{
+ QFETCH(const QUrl, source);
+ QFETCH(const QDate, date);
+ QQmlEngine e;
+ QQmlComponent component(&e, source);
+ QScopedPointer<QObject> obj(component.create());
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(obj.data());
+ QVERIFY(object != nullptr);
+ QCOMPARE(object->dateProperty(), date);
+ QVERIFY(object->boolProperty());
+}
+
+void tst_qqmlecmascript::checkDateTime_data()
+{
+ QTest::addColumn<QUrl>("source");
+ QTest::addColumn<QDateTime>("when");
+ // NB: JavaScript month-indices are Jan = 0 to Dec = 11; QDate's are Jan = 1 to Dec = 12.
+ QTest::newRow("denormal-March")
+ << testFileUrl("checkDateTime-denormal-March.qml")
+ << QDateTime(QDate(2019, 3, 1), QTime(0, 0, 0, 1), Qt::LocalTime);
+ QTest::newRow("denormal-leap")
+ << testFileUrl("checkDateTime-denormal-leap.qml")
+ << QDateTime(QDate(2020, 2, 29), QTime(23, 59, 59, 999), Qt::LocalTime);
+ QTest::newRow("denormal-hours")
+ << testFileUrl("checkDateTime-denormal-hours.qml")
+ << QDateTime(QDate(2020, 2, 29), QTime(0, 0), Qt::LocalTime);
+ QTest::newRow("denormal-minutes")
+ << testFileUrl("checkDateTime-denormal-minutes.qml")
+ << QDateTime(QDate(2020, 2, 29), QTime(0, 0), Qt::LocalTime);
+ QTest::newRow("denormal-seconds")
+ << testFileUrl("checkDateTime-denormal-seconds.qml")
+ << QDateTime(QDate(2020, 2, 29), QTime(0, 0), Qt::LocalTime);
+ QTest::newRow("October")
+ << testFileUrl("checkDateTime-October.qml")
+ << QDateTime(QDate(2019, 10, 3), QTime(12, 0), Qt::LocalTime);
+}
+
+void tst_qqmlecmascript::checkDateTime()
+{
+ QFETCH(const QUrl, source);
+ QFETCH(const QDateTime, when);
+ QQmlEngine e;
+ QQmlComponent component(&e, source);
+ QScopedPointer<QObject> obj(component.create());
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(obj.data());
+ QVERIFY(object != nullptr);
+ QCOMPARE(object->dateTimeProperty(), when);
+ QVERIFY(object->boolProperty());
+}
+
void tst_qqmlecmascript::idShortcutInvalidates()
{
QQmlEngine engine;