Skip to content

Commit

Permalink
fix daylight time in QTimeZone on Android
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Eskil Abrahamsen Blomfeldt <[email protected]>
  • Loading branch information
drew-parsons committed Dec 11, 2014
1 parent c9b9999 commit 0478bc1
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
52 changes: 52 additions & 0 deletions src/corelib/tools/qtimezoneprivate_android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;");
Expand Down
2 changes: 2 additions & 0 deletions src/corelib/tools/qtimezoneprivate_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,8 @@ class QAndroidTimeZonePrivate Q_DECL_FINAL : public QTimeZonePrivate
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;
Expand Down

0 comments on commit 0478bc1

Please sign in to comment.