aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2021-07-28 12:10:51 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-08-13 10:39:03 +0000
commita18926c736bf9de6bd652c8bb1799d4678001341 (patch)
tree6457a9aa94c2f6e12f6b780c0751f6db2718e861
parent2c3ea30205efef22146f3c7218d60b39fee991c2 (diff)
Use QDateTime to get offsets for emscripten (wasm)
Since our wasm implementation doesn't have access to time-zone data by default, but its QDateTime implementation does manage to get offsets right for local time, use it as fall-back for V4's Date implementation's DaylightSavingTA() and getLocalTZA(). This implementation might also be viable for other cases without timezone support (and a way to reset it when the system zone has changed), but we'll need to experiment to find out. For now, since we have nothing better for wasm, use it there. In passing, update a comment about a bug report against the ECMA spec to say it's been fixed (and we're compatible with the result). Fixes: QTBUG-95314 Change-Id: I40c1537815ada950dc0b5cebd4d641f7bfc45bd9 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Lorn Potter <lorn.potter@gmail.com> (cherry picked from commit 373897481fb930055e6e89035b1055f8dd80b83f) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 389e9351e7..9b751fbeaa 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -78,10 +78,21 @@
QTBUG-75585 for an explanation and possible workarounds.
*/
#define USE_QTZ_SYSTEM_ZONE
+#elif defined(Q_OS_WASM)
+/*
+ TODO: evaluate using this version of the code more generally, rather than
+ the #else branches of the various USE_QTZ_SYSTEM_ZONE choices. It might even
+ work better than the timezone variant; experiments needed.
+*/
+// Kludge around the lack of time-zone info using QDateTime.
+// It uses localtime() and friends to determine offsets from UTC.
+#define USE_QDT_LOCAL_TIME
#endif
#ifdef USE_QTZ_SYSTEM_ZONE
#include <QtCore/QTimeZone>
+#elif defined(USE_QDT_LOCAL_TIME)
+// QDateTime already included above
#else
# ifdef Q_OS_WIN
# include <windows.h>
@@ -356,6 +367,7 @@ static inline double MakeDate(double day, double time)
mean a whole day of DST offset for some zones, that have crossed the
international date line. This shall confuse client code.) The bug report
against the ECMAScript spec is https://github.com/tc39/ecma262/issues/725
+ and they've now changed the spec so that the following conforms to it ;^>
*/
static inline double DaylightSavingTA(double t, double localTZA) // t is a UTC time
@@ -363,6 +375,12 @@ static inline double DaylightSavingTA(double t, double localTZA) // t is a UTC t
return QTimeZone::systemTimeZone().offsetFromUtc(
QDateTime::fromMSecsSinceEpoch(qint64(t), Qt::UTC)) * 1e3 - localTZA;
}
+#elif defined(USE_QDT_LOCAL_TIME)
+static inline double DaylightSavingTA(double t, double localTZA) // t is a UTC time
+{
+ return QDateTime::fromMSecsSinceEpoch(qint64(t), Qt::UTC
+ ).toLocalTime().offsetFromUtc() * 1e3 - localTZA;
+}
#else
// This implementation fails to take account of past changes in standard offset.
static inline double DaylightSavingTA(double t, double /*localTZA*/)
@@ -721,6 +739,26 @@ static double getLocalTZA()
// TODO: QTimeZone::resetSystemTimeZone(), see QTBUG-56899 and comment above.
// Standard offset, with no daylight-savings adjustment, in ms:
return QTimeZone::systemTimeZone().standardTimeOffset(QDateTime::currentDateTime()) * 1e3;
+#elif defined(USE_QDT_LOCAL_TIME)
+ QDate today = QDate::currentDate();
+ QDateTime near = today.startOfDay(Qt::LocalTime);
+ // Early out if we're in standard time anyway:
+ if (!near.isDaylightTime())
+ return near.offsetFromUtc() * 1000;
+ int year, month;
+ today.getDate(&year, &month, nullptr);
+ // One of the solstices is probably in standard time:
+ QDate summer(year, 6, 21), winter(year - (month < 7 ? 1 : 0), 12, 21);
+ // But check the one closest to the present by preference, in case there's a
+ // standard time offset change between them:
+ QDateTime far = summer.startOfDay(Qt::LocalTime);
+ near = winter.startOfDay(Qt::LocalTime);
+ if (month > 3 && month < 10)
+ near.swap(far);
+ bool isDst = near.isDaylightTime();
+ if (isDst && far.isDaylightTime()) // Permanent DST, probably an hour west:
+ return (qMin(near.offsetFromUtc(), far.offsetFromUtc()) - 3600) * 1000;
+ return (isDst ? far : near).offsetFromUtc() * 1000;
#else
# ifdef Q_OS_WIN
TIME_ZONE_INFORMATION tzInfo;