summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/tools/qdatetime.cpp54
-rw-r--r--src/corelib/tools/qdatetime_p.h16
-rw-r--r--tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp30
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);