summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Hansen <kent.hansen@nokia.com>2010-08-31 11:15:30 +0200
committerKent Hansen <kent.hansen@nokia.com>2010-08-31 11:20:40 +0200
commitae574f7341f4f76a1f7de570cc3d56f77781e625 (patch)
treefd85a743bfb3917380b6134ee2a0b92956e3b2ba
parenteb1015c7bbf135af3656110a4d112377c1209db8 (diff)
downloadqt4-tools-ae574f7341f4f76a1f7de570cc3d56f77781e625.tar.gz
Fix QtScript Date <--> QDateTime (local time) conversion
This has already been fixed in 4.7 (QTBUG-9770), but the change is too big to backport. The general idea is the same: Only operate on UTC dates internally (since that's how JS dates are stored), and let QDateTime take care of converting from/to local dates as necessary. The fix itself shouldn't be merged to 4.7, but the autotests should. Task-number: QTBUG-9770 Reviewed-by: Jedrzej Nowacki
-rw-r--r--src/script/utils/qscriptdate.cpp11
-rw-r--r--tests/auto/qscriptengine/tst_qscriptengine.cpp66
2 files changed, 70 insertions, 7 deletions
diff --git a/src/script/utils/qscriptdate.cpp b/src/script/utils/qscriptdate.cpp
index 598025662c..3985adb136 100644
--- a/src/script/utils/qscriptdate.cpp
+++ b/src/script/utils/qscriptdate.cpp
@@ -320,8 +320,9 @@ qsreal FromDateTime(const QDateTime &dt)
return qSNaN();
if (!LocalTZA) // ### move
LocalTZA = getLocalTZA();
- QDate date = dt.date();
- QTime taim = dt.time();
+ QDateTime utc = dt.toUTC();
+ QDate date = utc.date();
+ QTime taim = utc.time();
int year = date.year();
int month = date.month() - 1;
int day = date.day();
@@ -331,8 +332,6 @@ qsreal FromDateTime(const QDateTime &dt)
int ms = taim.msec();
double t = MakeDate(MakeDay(year, month, day),
MakeTime(hours, mins, secs, ms));
- if (dt.timeSpec() == Qt::LocalTime)
- t = UTC(t);
return TimeClip(t);
}
@@ -348,8 +347,6 @@ QDateTime ToDateTime(qsreal t, Qt::TimeSpec spec)
return QDateTime();
if (!LocalTZA) // ### move
LocalTZA = getLocalTZA();
- if (spec == Qt::LocalTime)
- t = LocalTime(t);
int year = int(YearFromTime(t));
int month = int(MonthFromTime(t) + 1);
int day = int(DateFromTime(t));
@@ -357,7 +354,7 @@ QDateTime ToDateTime(qsreal t, Qt::TimeSpec spec)
int mins = MinFromTime(t);
int secs = SecFromTime(t);
int ms = msFromTime(t);
- return QDateTime(QDate(year, month, day), QTime(hours, mins, secs, ms), spec);
+ return QDateTime(QDate(year, month, day), QTime(hours, mins, secs, ms), Qt::UTC).toTimeSpec(spec);
}
} // namespace QScript
diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp
index bb01a42157..3bb9d17ce7 100644
--- a/tests/auto/qscriptengine/tst_qscriptengine.cpp
+++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp
@@ -166,6 +166,10 @@ private slots:
void qRegExpInport_data();
void qRegExpInport();
+ void dateRoundtripJSQtJS();
+ void dateRoundtripQtJSQt();
+ void dateConversionJSQt();
+ void dateConversionQtJS();
};
tst_QScriptEngine::tst_QScriptEngine()
@@ -4895,5 +4899,67 @@ void tst_QScriptEngine::qRegExpInport()
}
}
+// QScriptValue::toDateTime() returns a local time, whereas JS dates
+// are always stored as UTC. QtScript must respect the current time
+// zone, and correctly adjust for daylight saving time that may be in
+// effect at a given date (QTBUG-9770).
+void tst_QScriptEngine::dateRoundtripJSQtJS()
+{
+ uint secs = QDateTime(QDate(2009, 1, 1)).toUTC().toTime_t();
+ QScriptEngine eng;
+ for (int i = 0; i < 8000; ++i) {
+ QScriptValue jsDate = eng.evaluate(QString::fromLatin1("new Date(%0)").arg(secs * 1000.0));
+ QDateTime qtDate = jsDate.toDateTime();
+ QScriptValue jsDate2 = eng.newDate(qtDate);
+ if (jsDate2.toNumber() != jsDate.toNumber())
+ QFAIL(qPrintable(jsDate.toString()));
+ secs += 2*60*60;
+ }
+}
+
+void tst_QScriptEngine::dateRoundtripQtJSQt()
+{
+ QDateTime qtDate = QDateTime(QDate(2009, 1, 1));
+ QScriptEngine eng;
+ for (int i = 0; i < 8000; ++i) {
+ QScriptValue jsDate = eng.newDate(qtDate);
+ QDateTime qtDate2 = jsDate.toDateTime();
+ if (qtDate2 != qtDate)
+ QFAIL(qPrintable(qtDate.toString()));
+ qtDate = qtDate.addSecs(2*60*60);
+ }
+}
+
+void tst_QScriptEngine::dateConversionJSQt()
+{
+ uint secs = QDateTime(QDate(2009, 1, 1)).toUTC().toTime_t();
+ QScriptEngine eng;
+ for (int i = 0; i < 8000; ++i) {
+ QScriptValue jsDate = eng.evaluate(QString::fromLatin1("new Date(%0)").arg(secs * 1000.0));
+ QDateTime qtDate = jsDate.toDateTime();
+ QString qtUTCDateStr = qtDate.toUTC().toString(Qt::ISODate);
+ QString jsUTCDateStr = jsDate.property("toISOString").call(jsDate).toString();
+ jsUTCDateStr.chop(5); // get rid of milliseconds (".000Z")
+ if (qtUTCDateStr != jsUTCDateStr)
+ QFAIL(qPrintable(jsDate.toString()));
+ secs += 2*60*60;
+ }
+}
+
+void tst_QScriptEngine::dateConversionQtJS()
+{
+ QDateTime qtDate = QDateTime(QDate(2009, 1, 1));
+ QScriptEngine eng;
+ for (int i = 0; i < 8000; ++i) {
+ QScriptValue jsDate = eng.newDate(qtDate);
+ QString jsUTCDateStr = jsDate.property("toISOString").call(jsDate).toString();
+ jsUTCDateStr.chop(5); // get rid of milliseconds (".000Z")
+ QString qtUTCDateStr = qtDate.toUTC().toString(Qt::ISODate);
+ if (jsUTCDateStr != qtUTCDateStr)
+ QFAIL(qPrintable(qtDate.toString()));
+ qtDate = qtDate.addSecs(2*60*60);
+ }
+}
+
QTEST_MAIN(tst_QScriptEngine)
#include "tst_qscriptengine.moc"