diff options
author | Edward Welbourne <edward.welbourne@qt.io> | 2016-06-14 13:53:23 +0200 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2016-12-12 13:58:26 +0000 |
commit | 6e3f58cbbe313c3b843f69f3110e3c795fef6da8 (patch) | |
tree | d1654bb2305546d9785e1b5dfdd40df4f58bad90 /src/corelib/tools/qtimezoneprivate_android.cpp | |
parent | 57b0f54bb68760958ea315d9ba2000c2a738270d (diff) |
QDateTime, QTimeZone: fix mappings from zone time to UTC
Such mappings are ill-defined in the presence of daylight-savings time
(DST); at its transitions, you need information about whether DST is
active or not to determine the correct UTC value. Existing code did
not have a way to be told that hint, so could not be correct.
Fixing this required changing the (thankfully private) APIs by which
QDateTime accessed QTimeZone's information stipulated by zone time.
In QDateTime, this required propagating the needed hint, when DST
status was known.
QAndroidTimeZonePrivate overloaded QTimeZonePrivate::dataForLocalTime
with an implementation that works whenever !hasTransitions(); the base
implementation handled this case lamely, so I've moved the Android
implementation there, to have only one place for both re-writes.
Amended tst_QDateTime's expected failures; passing a date and time to
the constructor *is* ambiguous when the moment indicated is in a
transition. I have changed which way we resolve that ambiguity.
Added round-trip test of QDateTime's fromMSecs/toMSecs (but as a
QTimeZone test, since that's what's actually getting tested), based on
a test-case from Marko Kangas. Initially failed for various zones,
each at one hour-offset; and, on some platforms, for some zones, at
all offsets. These last revealed that a platform may claim to have
zone information yet, for some zones, lack it (or have very incomplete
information). In each case, despite this, the platform does give
offsetFromUtc(). (The test also found another pre-existing bug on
Linux; fixed in an earlier commit.)
To accommodate these gaps in transition data, the transition-based
code now falls back to the offsetFromUtc()-based code (used when there
are no transitions) if it can't find a previous transition (which, in
any case, it needs to do its job).
Task-number: QTBUG-56460
Task-number: QTBUG-56397
Task-number: QTBUG-52284
Change-Id: I2f7422a9e9d3767940b1901d887c6a2c1f36ac9f
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/tools/qtimezoneprivate_android.cpp')
-rw-r--r-- | src/corelib/tools/qtimezoneprivate_android.cpp | 52 |
1 files changed, 0 insertions, 52 deletions
diff --git a/src/corelib/tools/qtimezoneprivate_android.cpp b/src/corelib/tools/qtimezoneprivate_android.cpp index 53bf90f01d..e079fa0d63 100644 --- a/src/corelib/tools/qtimezoneprivate_android.cpp +++ b/src/corelib/tools/qtimezoneprivate_android.cpp @@ -207,58 +207,6 @@ 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 DST offset of one hour - qint64 standardUTCMSecs(forLocalMSecs - (standardTimeOffset(forLocalMSecs) * 1000)); - qint64 daylightUTCMsecs; - - // Check if daylight-saving time applies, - // checking also for DST boundaries - if (isDaylightTime(standardUTCMSecs)) { - // If DST 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)) { - // DST confirmed - UTCepochMSecs = daylightUTCMsecs; - } else { - // DST has just finished - UTCepochMSecs = standardUTCMSecs; - } - } else { - // Standard time indicated, but check for a false negative. - // Would a standard one-hour DST offset indicate DST? - daylightUTCMsecs = standardUTCMSecs - 3600000; // 3600000 MSECS_PER_HOUR - if (isDaylightTime(daylightUTCMsecs)) { - // DST may have just started, - // but double check against timezone's own DST offset - // (don't necessarily assume a one-hour offset) - daylightUTCMsecs = standardUTCMSecs - daylightTimeOffset(daylightUTCMsecs)*1000; - if (isDaylightTime(daylightUTCMsecs)) { - // DST 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;"); |