From 0478bc15bd3b4c616b4860e460600ba8877ee216 Mon Sep 17 00:00:00 2001 From: Drew Parsons Date: Sun, 7 Dec 2014 11:46:18 +1100 Subject: [PATCH] fix daylight time in QTimeZone on Android Android does not provide an API to access daylight time transitions, so the standard QTimeZonePrivate::dataForLocalTime only returns standard time without the daylight offset Therefore provide an override, QAndroidTimeZonePrivate::dataForLocalTime, which tests daylight time offsets directly rather than using transitions. Change-Id: Ia8adaf9af40da38aadfa7d22d9a3fe9da9ba24a8 Reviewed-by: Oswald Buddenhagen Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../tools/qtimezoneprivate_android.cpp | 52 +++++++++++++++++++ src/corelib/tools/qtimezoneprivate_p.h | 2 + 2 files changed, 54 insertions(+) diff --git a/src/corelib/tools/qtimezoneprivate_android.cpp b/src/corelib/tools/qtimezoneprivate_android.cpp index ab1ada2341..9d9bfc612d 100644 --- a/src/corelib/tools/qtimezoneprivate_android.cpp +++ b/src/corelib/tools/qtimezoneprivate_android.cpp @@ -201,6 +201,58 @@ QTimeZonePrivate::Data QAndroidTimeZonePrivate::previousTransition(qint64 before return invalidData(); } +// Since Android does not provide an API to access transitions, +// dataForLocalTime needs to be reimplemented without direct use of transitions +QTimeZonePrivate::Data QAndroidTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs) const +{ + if (!androidTimeZone.isValid()) { + return invalidData(); + } else { + qint64 UTCepochMSecs; + + // compare the UTC time with standard offset against normal daylight offset of one hour + qint64 standardUTCMSecs(forLocalMSecs - (standardTimeOffset(forLocalMSecs) * 1000)); + qint64 daylightUTCMsecs; + + // Check if daylight time does apply, + // checking also for daylight time boundaries + if (isDaylightTime(standardUTCMSecs)) { + // If daylight does apply, then standardUTCMSecs will be an hour or so ahead of the real epoch time + // so check that time + daylightUTCMsecs = standardUTCMSecs - daylightTimeOffset(standardUTCMSecs)*1000; + if (isDaylightTime(daylightUTCMsecs)) { + // daylight time confirmed + UTCepochMSecs = daylightUTCMsecs; + } else { + // daylight time has just finished + UTCepochMSecs = standardUTCMSecs; + } + } else { + // Standard time indicated, but check for a false negative. + // Would a standard one-hour daylight offset indicate daylight time? + daylightUTCMsecs = standardUTCMSecs - 3600000; // 3600000 MSECS_PER_HOUR + if (isDaylightTime(daylightUTCMsecs)) { + // daylight time may have just started, + // but double check against timezone's own daylight offset + // (don't necessarily assume a one-hour offset) + daylightUTCMsecs = standardUTCMSecs - daylightTimeOffset(daylightUTCMsecs)*1000; + if (isDaylightTime(daylightUTCMsecs)) { + // daylight time confirmed + UTCepochMSecs = daylightUTCMsecs; + } else { + // false positive, apply standard time after all + UTCepochMSecs = standardUTCMSecs; + } + } else { + // confirmed standard time + UTCepochMSecs = standardUTCMSecs; + } + } + + return data(UTCepochMSecs); + } +} + QByteArray QAndroidTimeZonePrivate::systemTimeZoneId() const { QJNIObjectPrivate androidSystemTimeZone = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;"); diff --git a/src/corelib/tools/qtimezoneprivate_p.h b/src/corelib/tools/qtimezoneprivate_p.h index 486f9c1ffa..6494ffe148 100644 --- a/src/corelib/tools/qtimezoneprivate_p.h +++ b/src/corelib/tools/qtimezoneprivate_p.h @@ -458,6 +458,8 @@ public: Data nextTransition(qint64 afterMSecsSinceEpoch) const Q_DECL_OVERRIDE; Data previousTransition(qint64 beforeMSecsSinceEpoch) const Q_DECL_OVERRIDE; + Data dataForLocalTime(qint64 forLocalMSecs) const Q_DECL_OVERRIDE; + QByteArray systemTimeZoneId() const Q_DECL_OVERRIDE; QSet availableTimeZoneIds() const Q_DECL_OVERRIDE;