summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKent Hansen <kent.hansen@nokia.com>2010-06-25 12:51:12 (GMT)
committerKent Hansen <kent.hansen@nokia.com>2010-06-25 14:22:34 (GMT)
commit0fa3175421a3329fe4cb3fb9f79f30807105b02f (patch)
tree4e555026bc55f38e732ce77ab6a571549d6d91a8 /src
parent860094d4e2614c0926f2af0e3538412ece31f726 (diff)
downloadQt-0fa3175421a3329fe4cb3fb9f79f30807105b02f.zip
Qt-0fa3175421a3329fe4cb3fb9f79f30807105b02f.tar.gz
Qt-0fa3175421a3329fe4cb3fb9f79f30807105b02f.tar.bz2
Fix conversion between JavaScript Date and QDateTime
Use JavaScriptCore's conversion functions rather than our own (incomplete) implementation. Specifically, this means daylight saving time is finally handled correctly on Windows. Task-number: QTBUG-9770 Reviewed-by: Olivier Goffart
Diffstat (limited to 'src')
-rw-r--r--src/script/api/qscriptengine.cpp47
-rw-r--r--src/script/api/qscriptengine_p.h10
-rw-r--r--src/script/script.pri1
-rw-r--r--src/script/utils/qscriptdate.cpp365
-rw-r--r--src/script/utils/qscriptdate_p.h52
-rw-r--r--src/script/utils/utils.pri5
6 files changed, 53 insertions, 427 deletions
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
index 655026c..7bccffe 100644
--- a/src/script/api/qscriptengine.cpp
+++ b/src/script/api/qscriptengine.cpp
@@ -438,6 +438,53 @@ qsreal ToNumber(const QString &value)
#endif
+static const qsreal MsPerSecond = 1000.0;
+
+static inline int MsFromTime(qsreal t)
+{
+ int r = int(::fmod(t, MsPerSecond));
+ return (r >= 0) ? r : r + int(MsPerSecond);
+}
+
+/*!
+ \internal
+ Converts a JS date value (milliseconds) to a QDateTime (local time).
+*/
+QDateTime MsToDateTime(JSC::ExecState *exec, qsreal t)
+{
+ if (qIsNaN(t))
+ return QDateTime();
+ JSC::GregorianDateTime tm;
+ JSC::msToGregorianDateTime(exec, t, /*output UTC=*/true, tm);
+ int ms = MsFromTime(t);
+ QDateTime convertedUTC = QDateTime(QDate(tm.year + 1900, tm.month + 1, tm.monthDay),
+ QTime(tm.hour, tm.minute, tm.second, ms), Qt::UTC);
+ return convertedUTC.toLocalTime();
+}
+
+/*!
+ \internal
+ Converts a QDateTime to a JS date value (milliseconds).
+*/
+qsreal DateTimeToMs(JSC::ExecState *exec, const QDateTime &dt)
+{
+ if (!dt.isValid())
+ return qSNaN();
+ QDateTime utc = dt.toUTC();
+ QDate date = utc.date();
+ QTime time = utc.time();
+ JSC::GregorianDateTime tm;
+ tm.year = date.year() - 1900;
+ tm.month = date.month() - 1;
+ tm.monthDay = date.day();
+ tm.weekDay = date.dayOfWeek();
+ tm.yearDay = date.dayOfYear();
+ tm.hour = time.hour();
+ tm.minute = time.minute();
+ tm.second = time.second();
+ return JSC::gregorianDateTimeToMS(exec, tm, time.msec(), /*inputIsUTC=*/true);
+}
+
void GlobalClientData::mark(JSC::MarkStack& markStack)
{
engine->mark(markStack);
diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h
index 1b35704..c71465d 100644
--- a/src/script/api/qscriptengine_p.h
+++ b/src/script/api/qscriptengine_p.h
@@ -50,7 +50,6 @@
#include "bridge/qscriptobject_p.h"
#include "bridge/qscriptqobject_p.h"
#include "bridge/qscriptvariant_p.h"
-#include "utils/qscriptdate_p.h"
#include "DateConstructor.h"
#include "DateInstance.h"
@@ -119,6 +118,9 @@ namespace QScript
inline QString ToString(qsreal);
#endif
+ QDateTime MsToDateTime(JSC::ExecState *, qsreal);
+ qsreal DateTimeToMs(JSC::ExecState *, const QDateTime &);
+
//some conversion helper functions
inline QScriptEnginePrivate *scriptEngineFromExec(const JSC::ExecState *exec);
bool isFunction(JSC::JSValue value);
@@ -861,7 +863,7 @@ inline JSC::JSValue QScriptEnginePrivate::newDate(JSC::ExecState *exec, qsreal v
inline JSC::JSValue QScriptEnginePrivate::newDate(JSC::ExecState *exec, const QDateTime &value)
{
- return newDate(exec, QScript::FromDateTime(value));
+ return newDate(exec, QScript::DateTimeToMs(exec, value));
}
inline JSC::JSValue QScriptEnginePrivate::newObject()
@@ -994,12 +996,12 @@ inline JSC::UString QScriptEnginePrivate::toString(JSC::ExecState *exec, JSC::JS
return str;
}
-inline QDateTime QScriptEnginePrivate::toDateTime(JSC::ExecState *, JSC::JSValue value)
+inline QDateTime QScriptEnginePrivate::toDateTime(JSC::ExecState *exec, JSC::JSValue value)
{
if (!isDate(value))
return QDateTime();
qsreal t = static_cast<JSC::DateInstance*>(JSC::asObject(value))->internalNumber();
- return QScript::ToDateTime(t, Qt::LocalTime);
+ return QScript::MsToDateTime(exec, t);
}
inline QObject *QScriptEnginePrivate::toQObject(JSC::ExecState *exec, JSC::JSValue value)
diff --git a/src/script/script.pri b/src/script/script.pri
index 2ee1a82..9cd71d3 100644
--- a/src/script/script.pri
+++ b/src/script/script.pri
@@ -1,4 +1,3 @@
include($$PWD/api/api.pri)
include($$PWD/bridge/bridge.pri)
include($$PWD/parser/parser.pri)
-include($$PWD/utils/utils.pri)
diff --git a/src/script/utils/qscriptdate.cpp b/src/script/utils/qscriptdate.cpp
deleted file mode 100644
index 5980256..0000000
--- a/src/script/utils/qscriptdate.cpp
+++ /dev/null
@@ -1,365 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtScript module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL-ONLY$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qscriptdate_p.h"
-
-#include <QtCore/qnumeric.h>
-#include <QtCore/qstringlist.h>
-
-#include <math.h>
-
-#ifndef Q_WS_WIN
-# include <time.h>
-# include <sys/time.h>
-#else
-# include <windows.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-namespace QScript {
-
-qsreal ToInteger(qsreal n);
-
-static const qsreal HoursPerDay = 24.0;
-static const qsreal MinutesPerHour = 60.0;
-static const qsreal SecondsPerMinute = 60.0;
-static const qsreal msPerSecond = 1000.0;
-static const qsreal msPerMinute = 60000.0;
-static const qsreal msPerHour = 3600000.0;
-static const qsreal msPerDay = 86400000.0;
-
-static qsreal LocalTZA = 0.0; // initialized at startup
-
-static inline qsreal TimeWithinDay(qsreal t)
-{
- qsreal r = ::fmod(t, msPerDay);
- return (r >= 0) ? r : r + msPerDay;
-}
-
-static inline int HourFromTime(qsreal t)
-{
- int r = int(::fmod(::floor(t / msPerHour), HoursPerDay));
- return (r >= 0) ? r : r + int(HoursPerDay);
-}
-
-static inline int MinFromTime(qsreal t)
-{
- int r = int(::fmod(::floor(t / msPerMinute), MinutesPerHour));
- return (r >= 0) ? r : r + int(MinutesPerHour);
-}
-
-static inline int SecFromTime(qsreal t)
-{
- int r = int(::fmod(::floor(t / msPerSecond), SecondsPerMinute));
- return (r >= 0) ? r : r + int(SecondsPerMinute);
-}
-
-static inline int msFromTime(qsreal t)
-{
- int r = int(::fmod(t, msPerSecond));
- return (r >= 0) ? r : r + int(msPerSecond);
-}
-
-static inline qsreal Day(qsreal t)
-{
- return ::floor(t / msPerDay);
-}
-
-static inline qsreal DaysInYear(qsreal y)
-{
- if (::fmod(y, 4))
- return 365;
-
- else if (::fmod(y, 100))
- return 366;
-
- else if (::fmod(y, 400))
- return 365;
-
- return 366;
-}
-
-static inline qsreal DayFromYear(qsreal y)
-{
- return 365 * (y - 1970)
- + ::floor((y - 1969) / 4)
- - ::floor((y - 1901) / 100)
- + ::floor((y - 1601) / 400);
-}
-
-static inline qsreal TimeFromYear(qsreal y)
-{
- return msPerDay * DayFromYear(y);
-}
-
-static inline qsreal YearFromTime(qsreal t)
-{
- int y = 1970;
- y += (int) ::floor(t / (msPerDay * 365.2425));
-
- qsreal t2 = TimeFromYear(y);
- return (t2 > t) ? y - 1 : ((t2 + msPerDay * DaysInYear(y)) <= t) ? y + 1 : y;
-}
-
-static inline bool InLeapYear(qsreal t)
-{
- qsreal x = DaysInYear(YearFromTime(t));
- if (x == 365)
- return 0;
-
- Q_ASSERT (x == 366);
- return 1;
-}
-
-static inline qsreal DayWithinYear(qsreal t)
-{
- return Day(t) - DayFromYear(YearFromTime(t));
-}
-
-static inline qsreal MonthFromTime(qsreal t)
-{
- qsreal d = DayWithinYear(t);
- qsreal l = InLeapYear(t);
-
- if (d < 31.0)
- return 0;
-
- else if (d < 59.0 + l)
- return 1;
-
- else if (d < 90.0 + l)
- return 2;
-
- else if (d < 120.0 + l)
- return 3;
-
- else if (d < 151.0 + l)
- return 4;
-
- else if (d < 181.0 + l)
- return 5;
-
- else if (d < 212.0 + l)
- return 6;
-
- else if (d < 243.0 + l)
- return 7;
-
- else if (d < 273.0 + l)
- return 8;
-
- else if (d < 304.0 + l)
- return 9;
-
- else if (d < 334.0 + l)
- return 10;
-
- else if (d < 365.0 + l)
- return 11;
-
- return qSNaN(); // ### assert?
-}
-
-static inline qsreal DateFromTime(qsreal t)
-{
- int m = (int) ToInteger(MonthFromTime(t));
- qsreal d = DayWithinYear(t);
- qsreal l = InLeapYear(t);
-
- switch (m) {
- case 0: return d + 1.0;
- case 1: return d - 30.0;
- case 2: return d - 58.0 - l;
- case 3: return d - 89.0 - l;
- case 4: return d - 119.0 - l;
- case 5: return d - 150.0 - l;
- case 6: return d - 180.0 - l;
- case 7: return d - 211.0 - l;
- case 8: return d - 242.0 - l;
- case 9: return d - 272.0 - l;
- case 10: return d - 303.0 - l;
- case 11: return d - 333.0 - l;
- }
-
- return qSNaN(); // ### assert
-}
-
-static inline qsreal WeekDay(qsreal t)
-{
- qsreal r = ::fmod (Day(t) + 4.0, 7.0);
- return (r >= 0) ? r : r + 7.0;
-}
-
-
-static inline qsreal MakeTime(qsreal hour, qsreal min, qsreal sec, qsreal ms)
-{
- return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec) * msPerSecond + ms;
-}
-
-static inline qsreal DayFromMonth(qsreal month, qsreal leap)
-{
- switch ((int) month) {
- case 0: return 0;
- case 1: return 31.0;
- case 2: return 59.0 + leap;
- case 3: return 90.0 + leap;
- case 4: return 120.0 + leap;
- case 5: return 151.0 + leap;
- case 6: return 181.0 + leap;
- case 7: return 212.0 + leap;
- case 8: return 243.0 + leap;
- case 9: return 273.0 + leap;
- case 10: return 304.0 + leap;
- case 11: return 334.0 + leap;
- }
-
- return qSNaN(); // ### assert?
-}
-
-static qsreal MakeDay(qsreal year, qsreal month, qsreal day)
-{
- year += ::floor(month / 12.0);
-
- month = ::fmod(month, 12.0);
- if (month < 0)
- month += 12.0;
-
- qsreal t = TimeFromYear(year);
- qsreal leap = InLeapYear(t);
-
- day += ::floor(t / msPerDay);
- day += DayFromMonth(month, leap);
-
- return day - 1;
-}
-
-static inline qsreal MakeDate(qsreal day, qsreal time)
-{
- return day * msPerDay + time;
-}
-
-static inline qsreal DaylightSavingTA(double t)
-{
-#ifndef Q_WS_WIN
- long int tt = (long int)(t / msPerSecond);
- struct tm *tmtm = localtime((const time_t*)&tt);
- if (! tmtm)
- return 0;
- return (tmtm->tm_isdst > 0) ? msPerHour : 0;
-#else
- Q_UNUSED(t);
- /// ### implement me
- return 0;
-#endif
-}
-
-static inline qsreal LocalTime(qsreal t)
-{
- return t + LocalTZA + DaylightSavingTA(t);
-}
-
-static inline qsreal UTC(qsreal t)
-{
- return t - LocalTZA - DaylightSavingTA(t - LocalTZA);
-}
-
-static inline qsreal TimeClip(qsreal t)
-{
- if (! qIsFinite(t) || fabs(t) > 8.64e15)
- return qSNaN();
- return ToInteger(t);
-}
-
-static qsreal getLocalTZA()
-{
-#ifndef Q_WS_WIN
- struct tm* t;
- time_t curr;
- time(&curr);
- t = localtime(&curr);
- time_t locl = mktime(t);
- t = gmtime(&curr);
- time_t globl = mktime(t);
- return double(locl - globl) * 1000.0;
-#else
- TIME_ZONE_INFORMATION tzInfo;
- GetTimeZoneInformation(&tzInfo);
- return -tzInfo.Bias * 60.0 * 1000.0;
-#endif
-}
-
-/*!
- \internal
-
- Converts the QDateTime \a dt to an ECMA Date value (in UTC form).
-*/
-qsreal FromDateTime(const QDateTime &dt)
-{
- if (!dt.isValid())
- return qSNaN();
- if (!LocalTZA) // ### move
- LocalTZA = getLocalTZA();
- QDate date = dt.date();
- QTime taim = dt.time();
- int year = date.year();
- int month = date.month() - 1;
- int day = date.day();
- int hours = taim.hour();
- int mins = taim.minute();
- int secs = taim.second();
- 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);
-}
-
-/*!
- \internal
-
- Converts the ECMA Date value \tt (in UTC form) to QDateTime
- according to \a spec.
-*/
-QDateTime ToDateTime(qsreal t, Qt::TimeSpec spec)
-{
- if (qIsNaN(t))
- 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));
- int hours = HourFromTime(t);
- int mins = MinFromTime(t);
- int secs = SecFromTime(t);
- int ms = msFromTime(t);
- return QDateTime(QDate(year, month, day), QTime(hours, mins, secs, ms), spec);
-}
-
-} // namespace QScript
-
-QT_END_NAMESPACE
diff --git a/src/script/utils/qscriptdate_p.h b/src/script/utils/qscriptdate_p.h
deleted file mode 100644
index b9c9fd4..0000000
--- a/src/script/utils/qscriptdate_p.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtScript module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL-ONLY$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSCRIPTDATE_P_H
-#define QSCRIPTDATE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qdatetime.h>
-
-QT_BEGIN_NAMESPACE
-
-typedef double qsreal;
-
-namespace QScript
-{
- qsreal FromDateTime(const QDateTime &dt);
- QDateTime ToDateTime(qsreal t, Qt::TimeSpec spec);
-}
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/script/utils/utils.pri b/src/script/utils/utils.pri
deleted file mode 100644
index d8302d5..0000000
--- a/src/script/utils/utils.pri
+++ /dev/null
@@ -1,5 +0,0 @@
-SOURCES += \
- $$PWD/qscriptdate.cpp
-
-HEADERS += \
- $$PWD/qscriptdate_p.h