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 <oswald.buddenhagen@theqtcompany.com>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@theqtcompany.com>
This commit is contained in:
Drew Parsons 2014-12-07 11:46:18 +11:00
parent c9b99994b0
commit 0478bc15bd
2 changed files with 54 additions and 0 deletions

View File

@ -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;");

View File

@ -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<QByteArray> availableTimeZoneIds() const Q_DECL_OVERRIDE;