summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qtimezoneprivate.cpp
diff options
context:
space:
mode:
authorJohn Layt <jlayt@kde.org>2013-02-11 13:44:37 +0000
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-23 01:14:03 +0200
commit55f5b29d7975d7e642ec258e44ca23726e1dfa0d (patch)
treea962c946ed58690d67bba1982556f3cb97545969 /src/corelib/tools/qtimezoneprivate.cpp
parent8af776d4140c19baccb8e2767ed8b57cc79ccb06 (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.cpp65
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;