diff options
author | John Layt <jlayt@kde.org> | 2013-02-11 13:44:37 +0000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-23 01:14:03 +0200 |
commit | 55f5b29d7975d7e642ec258e44ca23726e1dfa0d (patch) | |
tree | a962c946ed58690d67bba1982556f3cb97545969 /src/corelib/tools/qtimezoneprivate.cpp | |
parent | 8af776d4140c19baccb8e2767ed8b57cc79ccb06 (diff) |
QDateTime - Add QTimeZone support
Add support to QDateTime for time zones using the new QTimeZone class.
[ChangeLog][QtCore][QDateTime] Add support for a new Qt::TimeZone
spec to be used with QTimeZone to define times in a specific
time zone.
Change-Id: I21bfa52a8ba8989b55bb74e025d1f2b2b623b2a7
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/tools/qtimezoneprivate.cpp')
-rw-r--r-- | src/corelib/tools/qtimezoneprivate.cpp | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp index 4a8d891759..8d5d60bf37 100644 --- a/src/corelib/tools/qtimezoneprivate.cpp +++ b/src/corelib/tools/qtimezoneprivate.cpp @@ -48,6 +48,10 @@ QT_BEGIN_NAMESPACE +enum { + MSECS_TRAN_WINDOW = 21600000 // 6 hour window for possible recent transitions +}; + /* Static utilities for looking up Windows ID tables */ @@ -242,6 +246,67 @@ QTimeZonePrivate::Data QTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const return invalidData(); } +// Private only method for use by QDateTime to convert local msecs to epoch msecs +// TODO Could be platform optimised if needed +QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs) const +{ + if (!hasDaylightTime() ||!hasTransitions()) { + // No daylight time means same offset for all local msecs + // Having daylight time but no transitions means we can't calculate, so use nearest + return data(forLocalMSecs - (standardTimeOffset(forLocalMSecs) * 1000)); + } + + // Get the transition for the local msecs which most of the time should be the right one + // Only around the transition times might it not be the right one + Data tran = previousTransition(forLocalMSecs); + Data nextTran; + + // If the local msecs is less than the real local time of the transition + // then get the previous transition to use instead + if (forLocalMSecs < tran.atMSecsSinceEpoch + (tran.offsetFromUtc * 1000)) { + while (forLocalMSecs < tran.atMSecsSinceEpoch + (tran.offsetFromUtc * 1000)) { + nextTran = tran; + tran = previousTransition(tran.atMSecsSinceEpoch); + } + } else { + // The zone msecs is after the transition, so check it is before the next tran + // If not try use the next transition instead + nextTran = nextTransition(tran.atMSecsSinceEpoch); + while (forLocalMSecs >= nextTran.atMSecsSinceEpoch + (nextTran.offsetFromUtc * 1000)) { + tran = nextTran; + nextTran = nextTransition(tran.atMSecsSinceEpoch); + } + } + + if (tran.daylightTimeOffset == 0) { + // If tran is in StandardTime, then need to check if falls close either daylight transition + // If it does, then it may need adjusting for missing hour or for second occurrence + qint64 diffPrevTran = forLocalMSecs + - (tran.atMSecsSinceEpoch + (tran.offsetFromUtc * 1000)); + qint64 diffNextTran = nextTran.atMSecsSinceEpoch + (nextTran.offsetFromUtc * 1000) + - forLocalMSecs; + if (diffPrevTran >= 0 && diffPrevTran < MSECS_TRAN_WINDOW) { + // If tran picked is for standard time check if changed from daylight in last 6 hours, + // as the local msecs may be ambiguous and represent two valid utc msecs. + // If in last 6 hours then get prev tran and if diff falls within the daylight offset + // then use the prev tran as we default to the FirstOccurrence + // TODO Check if faster to just always get prev tran, or if faster using 6 hour check. + Data dstTran = previousTransition(tran.atMSecsSinceEpoch); + if (dstTran.daylightTimeOffset > 0 && diffPrevTran < (dstTran.daylightTimeOffset * 1000)) + tran = dstTran; + } else if (diffNextTran >= 0 && diffNextTran <= (nextTran.daylightTimeOffset * 1000)) { + // If time falls within last hour of standard time then is actually the missing hour + // So return the next tran instead and adjust the local time to be valid + tran = nextTran; + forLocalMSecs = forLocalMSecs + (nextTran.daylightTimeOffset * 1000); + } + } + + // tran should now hold the right transition offset to use + tran.atMSecsSinceEpoch = forLocalMSecs - (tran.offsetFromUtc * 1000); + return tran; +} + bool QTimeZonePrivate::hasTransitions() const { return false; |