diff options
-rw-r--r-- | src/corelib/tools/qdatetime.cpp | 54 | ||||
-rw-r--r-- | src/corelib/tools/qdatetime_p.h | 16 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp | 30 |
3 files changed, 61 insertions, 39 deletions
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index d64d929d5a..4839560c51 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -2224,7 +2224,7 @@ static QString qt_tzname(QDateTimePrivate::DaylightStatus daylightStatus) #endif // Q_OS_WINCE } -// Calls the platform variant of mktime for the given date and time, +// Calls the platform variant of mktime for the given date, time and daylightStatus, // and updates the date, time, daylightStatus and abbreviation with the returned values // If the date falls outside the 1970 to 2037 range supported by mktime / time_t // then null date/time will be returned, you should adjust the date first if @@ -2288,7 +2288,10 @@ static qint64 qt_mktime(QDate *date, QTime *time, QDateTimePrivate::DaylightStat local.tm_year = yy - 1900; local.tm_wday = 0; local.tm_yday = 0; - local.tm_isdst = -1; + if (daylightStatus) + local.tm_isdst = int(*daylightStatus); + else + local.tm_isdst = -1; #if defined(Q_OS_WIN) int hh = local.tm_hour; #endif // Q_OS_WIN @@ -2481,7 +2484,7 @@ static bool epochMSecsToLocalTime(qint64 msecs, QDate *localDate, QTime *localTi // Convert a LocalTime expressed in local msecs encoding into a UTC epoch msecs // Optionally populate the returned values from mktime for the adjusted local -// date and time and daylight status +// date and time and daylight status. Uses daylightStatus in calculation if populated. static qint64 localMSecsToEpochMSecs(qint64 localMsecs, QDate *localDate = 0, QTime *localTime = 0, QDateTimePrivate::DaylightStatus *daylightStatus = 0, QString *abbreviation = 0, bool *ok = 0) @@ -2614,6 +2617,7 @@ void QDateTimePrivate::setTimeSpec(Qt::TimeSpec spec, int offsetSeconds) { clearValidDateTime(); clearTimeZoneCached(); + clearSetToDaylightStatus(); #ifndef QT_BOOTSTRAPPED m_timeZone = QTimeZone(); @@ -2688,6 +2692,30 @@ void QDateTimePrivate::getDateTime(QDate *date, QTime *time) const *time = QTime(); } +// Set the Daylight Status if LocalTime set via msecs +void QDateTimePrivate::setDaylightStatus(QDateTimePrivate::DaylightStatus status) +{ + if (status == DaylightTime) { + m_status = m_status & ~SetToStandardTime; + m_status = m_status | SetToDaylightTime; + } else if (status == StandardTime) { + m_status = m_status & ~SetToDaylightTime; + m_status = m_status | SetToStandardTime; + } else { + clearSetToDaylightStatus(); + } +} + +// Get the Daylight Status if LocalTime set via msecs +QDateTimePrivate::DaylightStatus QDateTimePrivate::daylightStatus() const +{ + if ((m_status & SetToDaylightTime) == SetToDaylightTime) + return DaylightTime; + if ((m_status & SetToStandardTime) == SetToStandardTime) + return StandardTime; + return UnknownDaylightTime; +} + // Check the UTC / offsetFromUTC validity void QDateTimePrivate::checkValidDateTime() { @@ -2748,12 +2776,14 @@ void QDateTimePrivate::refreshDateTime() QDate testDate; QTime testTime; qint64 epochMSecs = 0; + if (m_spec == Qt::LocalTime) { + DaylightStatus status = daylightStatus(); + epochMSecs = localMSecsToEpochMSecs(m_msecs, &testDate, &testTime, &status); #ifndef QT_BOOTSTRAPPED - if (m_spec == Qt::TimeZone) + } else { epochMSecs = zoneMSecsToEpochMSecs(m_msecs, m_timeZone, &testDate, &testTime); - else #endif // QT_BOOTSTRAPPED - epochMSecs = localMSecsToEpochMSecs(m_msecs, &testDate, &testTime); + } if (testDate == date && testTime == time) { setValidDateTime(); // Cache the offset to use in toMSecsSinceEpoch() @@ -3189,7 +3219,8 @@ QString QDateTime::timeZoneAbbreviation() const #endif // QT_BOOTSTRAPPED case Qt::LocalTime: { QString abbrev; - localMSecsToEpochMSecs(d->m_msecs, 0, 0, 0, &abbrev); + QDateTimePrivate::DaylightStatus status = d->daylightStatus(); + localMSecsToEpochMSecs(d->m_msecs, 0, 0, &status, &abbrev); return abbrev; } } @@ -3218,8 +3249,9 @@ bool QDateTime::isDaylightTime() const return d->m_timeZone.d->isDaylightTime(toMSecsSinceEpoch()); #endif // QT_BOOTSTRAPPED case Qt::LocalTime: { - QDateTimePrivate::DaylightStatus status; - localMSecsToEpochMSecs(d->m_msecs, 0, 0, &status, 0); + QDateTimePrivate::DaylightStatus status = d->daylightStatus(); + if (status == QDateTimePrivate::UnknownDaylightTime) + localMSecsToEpochMSecs(d->m_msecs, 0, 0, &status, 0); return (status == QDateTimePrivate::DaylightTime); } } @@ -3424,8 +3456,10 @@ void QDateTime::setMSecsSinceEpoch(qint64 msecs) case Qt::LocalTime: { QDate dt; QTime tm; - epochMSecsToLocalTime(msecs, &dt, &tm); + QDateTimePrivate::DaylightStatus status; + epochMSecsToLocalTime(msecs, &dt, &tm, &status); d->setDateTime(dt, tm); + d->setDaylightStatus(status); break; } } diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/tools/qdatetime_p.h index f52108d764..70771844d6 100644 --- a/src/corelib/tools/qdatetime_p.h +++ b/src/corelib/tools/qdatetime_p.h @@ -77,10 +77,10 @@ public: // Daylight Time Status enum DaylightStatus { - NoDaylightTime, - UnknownDaylightTime, - StandardTime, - DaylightTime + NoDaylightTime = -2, + UnknownDaylightTime = -1, + StandardTime = 0, + DaylightTime = 1 }; // Status of date/time @@ -90,7 +90,9 @@ public: ValidDate = 0x04, ValidTime = 0x08, ValidDateTime = 0x10, - TimeZoneCached = 0x20 + TimeZoneCached = 0x20, + SetToStandardTime = 0x40, + SetToDaylightTime = 0x80 }; Q_DECLARE_FLAGS(StatusFlags, StatusFlag) @@ -129,6 +131,9 @@ public: void setDateTime(const QDate &date, const QTime &time); void getDateTime(QDate *date, QTime *time) const; + void setDaylightStatus(DaylightStatus status); + DaylightStatus daylightStatus() const; + // Returns msecs since epoch, assumes offset value is current inline qint64 toMSecsSinceEpoch() const { return (m_msecs - (m_offsetFromUtc * 1000)); } @@ -146,6 +151,7 @@ public: inline bool isTimeZoneCached() const { return (m_status & TimeZoneCached) == TimeZoneCached; } inline void setTimeZoneCached() { m_status = m_status | TimeZoneCached; } inline void clearTimeZoneCached() { m_status = m_status & ~TimeZoneCached; } + inline void clearSetToDaylightStatus() { m_status = m_status & ~SetToStandardTime & ~SetToDaylightTime; } #ifndef QT_BOOTSTRAPPED static qint64 zoneMSecsToEpochMSecs(qint64 msecs, const QTimeZone &zone, diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index a282fcabd3..b8b970121c 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -2384,8 +2384,6 @@ void tst_QDateTime::daylightTransitions() const // 2011-10-30 03:00:00 CEST became 02:00:00 CET at msecs = 1319936400000 // 2012-03-25 02:00:00 CET became 03:00:00 CEST at msecs = 1332637200000 // 2012-10-28 03:00:00 CEST became 02:00:00 CET at msecs = 1351386000000 - const qint64 daylight2011 = 1301187600000; - const qint64 standard2011 = 1319936400000; const qint64 daylight2012 = 1332637200000; const qint64 standard2012 = 1351386000000; const qint64 msecsOneHour = 3600000; @@ -2535,10 +2533,6 @@ void tst_QDateTime::daylightTransitions() const QVERIFY(hourBefore.isValid()); QCOMPARE(hourBefore.date(), QDate(2012, 10, 28)); QCOMPARE(hourBefore.time(), QTime(2, 0, 0)); -#ifndef Q_OS_MAC - // Linux mktime bug uses last calculation - QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); -#endif // Q_OS_MAC QCOMPARE(hourBefore.toMSecsSinceEpoch(), standard2012 - msecsOneHour); // 1 msec before transition is 2:59:59.999 FirstOccurrence @@ -2546,7 +2540,6 @@ void tst_QDateTime::daylightTransitions() const QVERIFY(msecBefore.isValid()); QCOMPARE(msecBefore.date(), QDate(2012, 10, 28)); QCOMPARE(msecBefore.time(), QTime(2, 59, 59, 999)); - QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); QCOMPARE(msecBefore.toMSecsSinceEpoch(), standard2012 - 1); // At transition is 2:00:00 SecondOccurrence @@ -2554,10 +2547,6 @@ void tst_QDateTime::daylightTransitions() const QVERIFY(atTran.isValid()); QCOMPARE(atTran.date(), QDate(2012, 10, 28)); QCOMPARE(atTran.time(), QTime(2, 0, 0)); -#ifdef Q_OS_MAC - // Mac defaults to FirstOccurrence here - QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); -#endif // Q_OS_MAC QCOMPARE(atTran.toMSecsSinceEpoch(), standard2012); // 59:59.999 after transition is 2:59:59.999 SecondOccurrence @@ -2708,10 +2697,6 @@ void tst_QDateTime::daylightTransitions() const QVERIFY(test.isValid()); QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.time(), QTime(2, 0, 0)); -#ifdef Q_OS_WIN - // Windows uses SecondOccurrence - QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); -#endif // Q_OS_WIN QCOMPARE(test.toMSecsSinceEpoch(), standard2012 - msecsOneHour); // Add hour to tran FirstOccurrence to get to tran SecondOccurrence @@ -2724,11 +2709,10 @@ void tst_QDateTime::daylightTransitions() const QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); #endif // Q_OS_WIN QCOMPARE(test.time(), QTime(2, 0, 0)); -#ifndef Q_OS_MAC +#ifdef Q_OS_WIN // Windows uses SecondOccurrence - // Linux mktime bug uses last calculation QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); -#endif // Q_OS_MAC +#endif // Q_OS_WIN QCOMPARE(test.toMSecsSinceEpoch(), standard2012); // Add hour to tran SecondOccurrence to get to after tran FirstOccurrence @@ -2736,15 +2720,13 @@ void tst_QDateTime::daylightTransitions() const test = test.addMSecs(msecsOneHour); QVERIFY(test.isValid()); QCOMPARE(test.date(), QDate(2012, 10, 28)); -#ifndef Q_OS_WIN - // Mac uses FirstOccurrence - // Linux mktime bug uses last calculation +#ifdef Q_OS_MAC + // Mac uses FirstOccurrence, Windows uses SecondOccurrence, Linux uses last calculation QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); #endif // Q_OS_WIN QCOMPARE(test.time(), QTime(3, 0, 0)); -#ifndef Q_OS_WIN - // Mac uses FirstOccurrence - // Linux mktime bug uses last calculation +#ifdef Q_OS_MAC + // Mac uses FirstOccurrence, Windows uses SecondOccurrence, Linux uses last calculation QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); #endif // Q_OS_WIN QCOMPARE(test.toMSecsSinceEpoch(), standard2012 + msecsOneHour); |