Fix and clean up utterly confused (and confusing) transition tests

Various QDateTime tests relating to transitions
* used a nomenclature that made them confusing to thing about; and
* expected identically-initiallized variables to behave differently.

The latter, naturally, lead to "expected fail" tests.

Rewrote the tests to get the date-times they want to test at by means
that avoid the ambiguities inherent in QDateTime's lack of a way to
distinguish the two passes through the repeated hour in a fall-back
(QTBUG-79923) and added commented-out tests indicating what should be
true once that ambiguity is resolved. Verified the DST status is as
expected in the cases where that's the correct distinction between
date-times with the same date and time. Renamed various things to
(hopefully) make them more intelligible.

In the process, purged some leading 0s from numbers in code.

Fixes: QTBUG-68936
Change-Id: Id7a348995238b70dcb81a96edb8a3fa5315f86fa
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Edward Welbourne 2021-03-10 13:57:17 +01:00
parent 2933e67f45
commit 2d51dfbefa

View File

@ -2836,7 +2836,7 @@ void tst_QDateTime::fromStringStringFormat_data()
<< QString("1947-05-11 03:23:45.678 Europe/Berlin") << QString("1947-05-11 03:23:45.678 Europe/Berlin")
<< QString("yyyy-MM-dd hh:mm:ss.zzz t") << QString("yyyy-MM-dd hh:mm:ss.zzz t")
// That's in the hour skipped - expecting an invalid DateTime // That's in the hour skipped - expecting an invalid DateTime
<< QDateTime(QDate(1947, 05, 11), QTime(3, 23, 45, 678), berlintz); << QDateTime(QDate(1947, 5, 11), QTime(3, 23, 45, 678), berlintz);
} }
#endif #endif
QTest::newRow("late") << QString("9999-12-31T23:59:59.999Z") QTest::newRow("late") << QString("9999-12-31T23:59:59.999Z")
@ -2859,7 +2859,7 @@ void tst_QDateTime::fromStringStringFormat_data()
// test unicode // test unicode
QTest::newRow("unicode handling") << QString(u8"2005🤣06🤣28T07🤣57🤣30.001Z") QTest::newRow("unicode handling") << QString(u8"2005🤣06🤣28T07🤣57🤣30.001Z")
<< QString(u8"yyyy🤣MM🤣ddThh🤣mm🤣ss.zt") << QString(u8"yyyy🤣MM🤣ddThh🤣mm🤣ss.zt")
<< QDateTime(QDate(2005, 06, 28), QTime(07, 57, 30, 1), Qt::UTC); << QDateTime(QDate(2005, 6, 28), QTime(7, 57, 30, 1), Qt::UTC);
// QTBUG-84349 // QTBUG-84349
QTest::newRow("QTBUG-84349: positive sign in month") QTest::newRow("QTBUG-84349: positive sign in month")
@ -3299,9 +3299,13 @@ void tst_QDateTime::daylightTransitions() const
// 2011-10-30 03:00:00 CEST became 02:00:00 CET at msecs = 1319936400000 // 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-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 // 2012-10-28 03:00:00 CEST became 02:00:00 CET at msecs = 1351386000000
const qint64 daylight2012 = 1332637200000; QCOMPARE(QDate(2012, 3, 25).dayOfWeek(), 7);
const qint64 standard2012 = 1351386000000; QCOMPARE(QDate(2012, 10, 28).dayOfWeek(), 7);
const qint64 spring2012 = 1332637200000;
const qint64 autumn2012 = 1351386000000;
const qint64 msecsOneHour = 3600000; const qint64 msecsOneHour = 3600000;
QCOMPARE(spring2012, QDateTime(QDate(2012, 3, 25), QTime(1, 0), Qt::UTC).toMSecsSinceEpoch());
QCOMPARE(autumn2012, QDateTime(QDate(2012, 10, 28), QTime(1, 0), Qt::UTC).toMSecsSinceEpoch());
// Test for correct behviour for StandardTime -> DaylightTime transition, i.e. missing hour // Test for correct behviour for StandardTime -> DaylightTime transition, i.e. missing hour
@ -3311,38 +3315,38 @@ void tst_QDateTime::daylightTransitions() const
QVERIFY(before.isValid()); QVERIFY(before.isValid());
QCOMPARE(before.date(), QDate(2012, 3, 25)); QCOMPARE(before.date(), QDate(2012, 3, 25));
QCOMPARE(before.time(), QTime(1, 59, 59, 999)); QCOMPARE(before.time(), QTime(1, 59, 59, 999));
QCOMPARE(before.toMSecsSinceEpoch(), daylight2012 - 1); QCOMPARE(before.toMSecsSinceEpoch(), spring2012 - 1);
QDateTime missing(QDate(2012, 3, 25), QTime(2, 0)); QDateTime missing(QDate(2012, 3, 25), QTime(2, 0));
QVERIFY(!missing.isValid()); QVERIFY(!missing.isValid());
QCOMPARE(missing.date(), QDate(2012, 3, 25)); QCOMPARE(missing.date(), QDate(2012, 3, 25));
QCOMPARE(missing.time(), QTime(2, 0)); QCOMPARE(missing.time(), QTime(2, 0));
// datetimeparser relies on toMSecsSinceEpoch to still work: // datetimeparser relies on toMSecsSinceEpoch to still work:
QCOMPARE(missing.toMSecsSinceEpoch(), daylight2012); QCOMPARE(missing.toMSecsSinceEpoch(), spring2012);
QDateTime after(QDate(2012, 3, 25), QTime(3, 0)); QDateTime after(QDate(2012, 3, 25), QTime(3, 0));
QVERIFY(after.isValid()); QVERIFY(after.isValid());
QCOMPARE(after.date(), QDate(2012, 3, 25)); QCOMPARE(after.date(), QDate(2012, 3, 25));
QCOMPARE(after.time(), QTime(3, 0)); QCOMPARE(after.time(), QTime(3, 0));
QCOMPARE(after.toMSecsSinceEpoch(), daylight2012); QCOMPARE(after.toMSecsSinceEpoch(), spring2012);
// Test round-tripping of msecs // Test round-tripping of msecs
before.setMSecsSinceEpoch(daylight2012 - 1); before.setMSecsSinceEpoch(spring2012 - 1);
QVERIFY(before.isValid()); QVERIFY(before.isValid());
QCOMPARE(before.date(), QDate(2012, 3, 25)); QCOMPARE(before.date(), QDate(2012, 3, 25));
QCOMPARE(before.time(), QTime(1, 59, 59, 999)); QCOMPARE(before.time(), QTime(1, 59, 59, 999));
QCOMPARE(before.toMSecsSinceEpoch(), daylight2012 -1); QCOMPARE(before.toMSecsSinceEpoch(), spring2012 -1);
after.setMSecsSinceEpoch(daylight2012); after.setMSecsSinceEpoch(spring2012);
QVERIFY(after.isValid()); QVERIFY(after.isValid());
QCOMPARE(after.date(), QDate(2012, 3, 25)); QCOMPARE(after.date(), QDate(2012, 3, 25));
QCOMPARE(after.time(), QTime(3, 0)); QCOMPARE(after.time(), QTime(3, 0));
QCOMPARE(after.toMSecsSinceEpoch(), daylight2012); QCOMPARE(after.toMSecsSinceEpoch(), spring2012);
// Test changing time spec re-validates the date/time // Test changing time spec re-validates the date/time
QDateTime utc(QDate(2012, 3, 25), QTime(2, 00, 0), Qt::UTC); QDateTime utc(QDate(2012, 3, 25), QTime(2, 0), Qt::UTC);
QVERIFY(utc.isValid()); QVERIFY(utc.isValid());
QCOMPARE(utc.date(), QDate(2012, 3, 25)); QCOMPARE(utc.date(), QDate(2012, 3, 25));
QCOMPARE(utc.time(), QTime(2, 0)); QCOMPARE(utc.time(), QTime(2, 0));
@ -3383,272 +3387,300 @@ void tst_QDateTime::daylightTransitions() const
test = QDateTime(QDate(2012, 3, 25), QTime(1, 0)); test = QDateTime(QDate(2012, 3, 25), QTime(1, 0));
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QCOMPARE(test.toMSecsSinceEpoch(), daylight2012 - msecsOneHour); QCOMPARE(test.toMSecsSinceEpoch(), spring2012 - msecsOneHour);
test = test.addMSecs(msecsOneHour); test = test.addMSecs(msecsOneHour);
CHECK_SPRING_FORWARD(test); CHECK_SPRING_FORWARD(test);
if (handled) if (handled)
QCOMPARE(test.toMSecsSinceEpoch(), daylight2012); QCOMPARE(test.toMSecsSinceEpoch(), spring2012);
#undef CHECK_SPRING_FORWARD #undef CHECK_SPRING_FORWARD
// Test for correct behviour for DaylightTime -> StandardTime transition, i.e. second occurrence // Test for correct behviour for DaylightTime -> StandardTime transition, fall-back
// TODO (QTBUG-79923): Compare to results of direct QDateTime(date, time, fold)
// construction; see Prior/Post commented-out tests.
// Test setting date and time in first and second occurrence will be valid QDateTime autumnMidnight = QDate(2012, 10, 28).startOfDay();
QVERIFY(autumnMidnight.isValid());
// QCOMPARE(autumnMidnight, QDateTime(QDate(2012, 10, 28), QTime(2, 0), Prior));
QCOMPARE(autumnMidnight.date(), QDate(2012, 10, 28));
QCOMPARE(autumnMidnight.time(), QTime(0, 0));
QCOMPARE(autumnMidnight.toMSecsSinceEpoch(), autumn2012 - 3 * msecsOneHour);
// 1 hour before transition is 2:00:00 FirstOccurrence QDateTime startFirst = autumnMidnight.addMSecs(2 * msecsOneHour);
QDateTime hourBefore(QDate(2012, 10, 28), QTime(2, 0)); QVERIFY(startFirst.isValid());
QVERIFY(hourBefore.isValid()); // QCOMPARE(startFirst, QDateTime(QDate(2012, 10, 28), QTime(2, 0), Prior));
QCOMPARE(hourBefore.date(), QDate(2012, 10, 28)); QCOMPARE(startFirst.date(), QDate(2012, 10, 28));
QCOMPARE(hourBefore.time(), QTime(2, 0)); QCOMPARE(startFirst.time(), QTime(2, 0));
#ifdef Q_OS_WIN QCOMPARE(startFirst.toMSecsSinceEpoch(), autumn2012 - msecsOneHour);
// Windows uses SecondOccurrence
QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue);
#endif // Q_OS_WIN
QCOMPARE(hourBefore.toMSecsSinceEpoch(), standard2012 - msecsOneHour);
// 1 msec before transition is 2:59:59.999 FirstOccurrence // 1 msec before transition is 2:59:59.999 FirstOccurrence
QDateTime msecBefore(QDate(2012, 10, 28), QTime(2, 59, 59, 999)); QDateTime endFirst = startFirst.addMSecs(msecsOneHour - 1);
QVERIFY(msecBefore.isValid()); QVERIFY(endFirst.isValid());
QCOMPARE(msecBefore.date(), QDate(2012, 10, 28)); // QCOMPARE(endFirst, QDateTime(QDate(2012, 10, 28), QTime(2, 59, 59, 999), Prior));
QCOMPARE(msecBefore.time(), QTime(2, 59, 59, 999)); QCOMPARE(endFirst.date(), QDate(2012, 10, 28));
#if defined(Q_OS_DARWIN) || defined(Q_OS_WIN) || defined(Q_OS_QNX) || defined(Q_OS_ANDROID) QCOMPARE(endFirst.time(), QTime(2, 59, 59, 999));
// Win and Mac uses SecondOccurrence here QCOMPARE(endFirst.toMSecsSinceEpoch(), autumn2012 - 1);
QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue);
#endif // Q_OS_MAC
QCOMPARE(msecBefore.toMSecsSinceEpoch(), standard2012 - 1);
// At transition is 2:00:00 SecondOccurrence // At the transition, starting the second pass
QDateTime atTran(QDate(2012, 10, 28), QTime(2, 0)); QDateTime startRepeat = endFirst.addMSecs(1);
QVERIFY(atTran.isValid()); QVERIFY(startRepeat.isValid());
QCOMPARE(atTran.date(), QDate(2012, 10, 28)); // QCOMPARE(startRepeat, QDateTime(QDate(2012, 10, 28), QTime(2, 0), Post));
QCOMPARE(atTran.time(), QTime(2, 0)); QCOMPARE(startRepeat.date(), QDate(2012, 10, 28));
#ifndef Q_OS_WIN QCOMPARE(startRepeat.time(), QTime(2, 0));
// Windows uses SecondOccurrence QCOMPARE(startRepeat.toMSecsSinceEpoch(), autumn2012);
QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue);
#endif // Q_OS_WIN
QCOMPARE(atTran.toMSecsSinceEpoch(), standard2012);
// 59:59.999 after transition is 2:59:59.999 SecondOccurrence // 59:59.999 after transition is 2:59:59.999 SecondOccurrence
QDateTime afterTran(QDate(2012, 10, 28), QTime(2, 59, 59, 999)); QDateTime endRepeat = endFirst.addMSecs(msecsOneHour);
QVERIFY(afterTran.isValid()); QVERIFY(endRepeat.isValid());
QCOMPARE(afterTran.date(), QDate(2012, 10, 28)); // QCOMPARE(endRepeat, QDateTime(QDate(2012, 10, 28), QTime(2, 59, 59, 999), Post));
QCOMPARE(afterTran.time(), QTime(2, 59, 59, 999)); QCOMPARE(endRepeat.date(), QDate(2012, 10, 28));
#ifdef __GLIBCXX__ QCOMPARE(endRepeat.time(), QTime(2, 59, 59, 999));
// Linux (i.e. glibc) mktime bug reuses last calculation QCOMPARE(endRepeat.toMSecsSinceEpoch(), autumn2012 + msecsOneHour - 1);
QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue);
#endif // Q_OS_UNIX
QCOMPARE(afterTran.toMSecsSinceEpoch(), standard2012 + msecsOneHour - 1);
// 1 hour after transition is 3:00:00 FirstOccurrence // 1 hour after transition is 3:00:00 (not ambiguous)
QDateTime hourAfter(QDate(2012, 10, 28), QTime(3, 0)); QDateTime hourAfter = endRepeat.addMSecs(1);
QVERIFY(hourAfter.isValid()); QVERIFY(hourAfter.isValid());
QCOMPARE(hourAfter, QDateTime(QDate(2012, 10, 28), QTime(3, 0)));
QCOMPARE(hourAfter.date(), QDate(2012, 10, 28)); QCOMPARE(hourAfter.date(), QDate(2012, 10, 28));
QCOMPARE(hourAfter.time(), QTime(3, 0)); QCOMPARE(hourAfter.time(), QTime(3, 0));
QCOMPARE(hourAfter.toMSecsSinceEpoch(), standard2012 + msecsOneHour); QCOMPARE(hourAfter.toMSecsSinceEpoch(), autumn2012 + msecsOneHour);
// Test round-tripping of msecs // Test round-tripping of msecs
// 1 hour before transition is 2:00:00 FirstOccurrence // 1 hour before transition is 2:00:00 FirstOccurrence
hourBefore.setMSecsSinceEpoch(standard2012 - msecsOneHour); startFirst.setMSecsSinceEpoch(autumn2012 - msecsOneHour);
QVERIFY(hourBefore.isValid()); QVERIFY(startFirst.isValid());
QCOMPARE(hourBefore.date(), QDate(2012, 10, 28)); QCOMPARE(startFirst.date(), QDate(2012, 10, 28));
QCOMPARE(hourBefore.time(), QTime(2, 0)); QCOMPARE(startFirst.time(), QTime(2, 0));
QCOMPARE(hourBefore.toMSecsSinceEpoch(), standard2012 - msecsOneHour); QCOMPARE(startFirst.toMSecsSinceEpoch(), autumn2012 - msecsOneHour);
// 1 msec before transition is 2:59:59.999 FirstOccurrence // 1 msec before transition is 2:59:59.999 FirstOccurrence
msecBefore.setMSecsSinceEpoch(standard2012 - 1); endFirst.setMSecsSinceEpoch(autumn2012 - 1);
QVERIFY(msecBefore.isValid()); QVERIFY(endFirst.isValid());
QCOMPARE(msecBefore.date(), QDate(2012, 10, 28)); QCOMPARE(endFirst.date(), QDate(2012, 10, 28));
QCOMPARE(msecBefore.time(), QTime(2, 59, 59, 999)); QCOMPARE(endFirst.time(), QTime(2, 59, 59, 999));
QCOMPARE(msecBefore.toMSecsSinceEpoch(), standard2012 - 1); QCOMPARE(endFirst.toMSecsSinceEpoch(), autumn2012 - 1);
// At transition is 2:00:00 SecondOccurrence // At transition is 2:00:00 SecondOccurrence
atTran.setMSecsSinceEpoch(standard2012); startRepeat.setMSecsSinceEpoch(autumn2012);
QVERIFY(atTran.isValid()); QVERIFY(startRepeat.isValid());
QCOMPARE(atTran.date(), QDate(2012, 10, 28)); QCOMPARE(startRepeat.date(), QDate(2012, 10, 28));
QCOMPARE(atTran.time(), QTime(2, 0)); QCOMPARE(startRepeat.time(), QTime(2, 0));
QCOMPARE(atTran.toMSecsSinceEpoch(), standard2012); QCOMPARE(startRepeat.toMSecsSinceEpoch(), autumn2012);
// 59:59.999 after transition is 2:59:59.999 SecondOccurrence // 59:59.999 after transition is 2:59:59.999 SecondOccurrence
afterTran.setMSecsSinceEpoch(standard2012 + msecsOneHour - 1); endRepeat.setMSecsSinceEpoch(autumn2012 + msecsOneHour - 1);
QVERIFY(afterTran.isValid()); QVERIFY(endRepeat.isValid());
QCOMPARE(afterTran.date(), QDate(2012, 10, 28)); QCOMPARE(endRepeat.date(), QDate(2012, 10, 28));
QCOMPARE(afterTran.time(), QTime(2, 59, 59, 999)); QCOMPARE(endRepeat.time(), QTime(2, 59, 59, 999));
QCOMPARE(afterTran.toMSecsSinceEpoch(), standard2012 + msecsOneHour - 1); QCOMPARE(endRepeat.toMSecsSinceEpoch(), autumn2012 + msecsOneHour - 1);
// 1 hour after transition is 3:00:00 FirstOccurrence // 1 hour after transition is 3:00:00 (unambiguous)
hourAfter.setMSecsSinceEpoch(standard2012 + msecsOneHour); hourAfter.setMSecsSinceEpoch(autumn2012 + msecsOneHour);
QVERIFY(hourAfter.isValid()); QVERIFY(hourAfter.isValid());
QCOMPARE(hourAfter.date(), QDate(2012, 10, 28)); QCOMPARE(hourAfter.date(), QDate(2012, 10, 28));
QCOMPARE(hourAfter.time(), QTime(3, 0)); QCOMPARE(hourAfter.time(), QTime(3, 0));
QCOMPARE(hourAfter.toMSecsSinceEpoch(), standard2012 + msecsOneHour); QCOMPARE(hourAfter.toMSecsSinceEpoch(), autumn2012 + msecsOneHour);
// Test date maths, result is always FirstOccurrence // Test date maths
// Add year to get to tran FirstOccurrence // Add year to a DST moment to hit start of first pass:
test = QDateTime(QDate(2011, 10, 28), QTime(2, 0)); test = QDateTime(QDate(2011, 10, 28), QTime(2, 0));
QVERIFY(test.isDaylightTime()); // Before last Sunday in month
test = test.addYears(1); test = test.addYears(1);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(test.isDaylightTime());
QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.date(), QDate(2012, 10, 28));
QCOMPARE(test.time(), QTime(2, 0)); QCOMPARE(test.time(), QTime(2, 0));
#ifdef Q_OS_WIN // QCOMPARE(test, QDateTime(QDate(2012, 10, 28), QTime(2, 0), Prior));
// Windows uses SecondOccurrence QCOMPARE(test.toMSecsSinceEpoch(), autumn2012 - msecsOneHour);
QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue);
#endif // Q_OS_WIN
QCOMPARE(test.toMSecsSinceEpoch(), standard2012 - msecsOneHour);
// Add year to get to after tran FirstOccurrence // Subtract year from post-tran time to hit start of second pass:
test = QDateTime(QDate(2013, 10, 28), QTime(2, 0));
QVERIFY(!test.isDaylightTime()); // After last Sundy in month
test = test.addYears(-1);
QVERIFY(test.isValid());
QVERIFY(!test.isDaylightTime());
QCOMPARE(test.date(), QDate(2012, 10, 28));
QCOMPARE(test.time(), QTime(2, 0));
// QCOMPARE(test, QDateTime(QDate(2012, 10, 28), QTime(2, 0), Post));
QCOMPARE(test.toMSecsSinceEpoch(), autumn2012);
// Add year to get to after the repeated hour
test = QDateTime(QDate(2011, 10, 28), QTime(3, 0)); test = QDateTime(QDate(2011, 10, 28), QTime(3, 0));
QVERIFY(test.isDaylightTime()); // Before last Sunday in month
test = test.addYears(1); test = test.addYears(1);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(!test.isDaylightTime());
QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.date(), QDate(2012, 10, 28));
QCOMPARE(test.time(), QTime(3, 0)); QCOMPARE(test.time(), QTime(3, 0));
QCOMPARE(test.toMSecsSinceEpoch(), standard2012 + msecsOneHour); QCOMPARE(test, QDateTime(QDate(2012, 10, 28), QTime(3, 0)));
QCOMPARE(test.toMSecsSinceEpoch(), autumn2012 + msecsOneHour);
// Add year to tran FirstOccurrence // Add year to start of first pass:
test = QDateTime(QDate(2011, 10, 30), QTime(2, 0)); test = QDateTime(QDate(2011, 10, 30), QTime(1, 0)).addMSecs(msecsOneHour);
QVERIFY(test.isDaylightTime());
test = test.addYears(1); test = test.addYears(1);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(!test.isDaylightTime()); // After last Sunday in month
QCOMPARE(test.date(), QDate(2012, 10, 30)); QCOMPARE(test.date(), QDate(2012, 10, 30));
QCOMPARE(test.time(), QTime(2, 0)); QCOMPARE(test.time(), QTime(2, 0));
QCOMPARE(test, QDateTime(QDate(2012, 10, 30), QTime(2, 0)));
// Add year to tran SecondOccurrence // Add year to start of second pass:
test = QDateTime(QDate(2011, 10, 30), QTime(2, 0)); // TODO SecondOccurrence test = QDateTime(QDate(2011, 10, 30), QTime(3, 0)).addMSecs(-msecsOneHour);
QVERIFY(!test.isDaylightTime());
test = test.addYears(1); test = test.addYears(1);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(!test.isDaylightTime()); // Same as before
QCOMPARE(test.date(), QDate(2012, 10, 30)); QCOMPARE(test.date(), QDate(2012, 10, 30));
QCOMPARE(test.time(), QTime(2, 0)); QCOMPARE(test.time(), QTime(2, 0));
QCOMPARE(test, QDateTime(QDate(2012, 10, 30), QTime(2, 0)));
// Add year to after tran FirstOccurrence // Add year to after second pass:
test = QDateTime(QDate(2011, 10, 30), QTime(3, 0)); test = QDateTime(QDate(2011, 10, 30), QTime(3, 0));
QVERIFY(!test.isDaylightTime());
test = test.addYears(1); test = test.addYears(1);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(!test.isDaylightTime());
QCOMPARE(test.date(), QDate(2012, 10, 30)); QCOMPARE(test.date(), QDate(2012, 10, 30));
QCOMPARE(test.time(), QTime(3, 0)); QCOMPARE(test.time(), QTime(3, 0));
QCOMPARE(test, QDateTime(QDate(2012, 10, 30), QTime(3, 0)));
// Add month to get to tran FirstOccurrence // Add month to get to start of first pass
test = QDateTime(QDate(2012, 9, 28), QTime(2, 0)); test = QDateTime(QDate(2012, 9, 28), QTime(2, 0));
QVERIFY(test.isDaylightTime());
test = test.addMonths(1); test = test.addMonths(1);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(test.isDaylightTime());
QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.date(), QDate(2012, 10, 28));
QCOMPARE(test.time(), QTime(2, 0)); QCOMPARE(test.time(), QTime(2, 0));
#ifdef Q_OS_WIN // QCOMPARE(test, QDateTime(QDate(2012, 10, 28), QTime(2, 0), Prior));
// Windows uses SecondOccurrence QCOMPARE(test.toMSecsSinceEpoch(), autumn2012 - msecsOneHour);
QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue);
#endif // Q_OS_WIN
QCOMPARE(test.toMSecsSinceEpoch(), standard2012 - msecsOneHour);
// Add month to get to after tran FirstOccurrence // Add month to get to after second pass (unambiguous)
test = QDateTime(QDate(2012, 9, 28), QTime(3, 0)); test = QDateTime(QDate(2012, 9, 28), QTime(3, 0));
QVERIFY(test.isDaylightTime());
test = test.addMonths(1); test = test.addMonths(1);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(!test.isDaylightTime());
QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.date(), QDate(2012, 10, 28));
QCOMPARE(test.time(), QTime(3, 0)); QCOMPARE(test.time(), QTime(3, 0));
QCOMPARE(test.toMSecsSinceEpoch(), standard2012 + msecsOneHour); QCOMPARE(test, QDateTime(QDate(2012, 10, 28), QTime(3, 0)));
QCOMPARE(test.toMSecsSinceEpoch(), autumn2012 + msecsOneHour);
// Add month to tran FirstOccurrence // Add month to start of first pass
test = QDateTime(QDate(2011, 10, 30), QTime(2, 0)); test = QDateTime(QDate(2011, 10, 30), QTime(1, 0)).addMSecs(msecsOneHour);
QVERIFY(test.isDaylightTime());
test = test.addMonths(1); test = test.addMonths(1);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(!test.isDaylightTime());
QCOMPARE(test.date(), QDate(2011, 11, 30)); QCOMPARE(test.date(), QDate(2011, 11, 30));
QCOMPARE(test.time(), QTime(2, 0)); QCOMPARE(test.time(), QTime(2, 0));
QCOMPARE(test, QDateTime(QDate(2011, 11, 30), QTime(2, 0)));
// Add month to tran SecondOccurrence // Add month to end of second pass
test = QDateTime(QDate(2011, 10, 30), QTime(2, 0)); // TODO SecondOccurrence test = QDateTime(QDate(2011, 10, 30), QTime(3, 0)).addMSecs(-msecsOneHour);
QVERIFY(!test.isDaylightTime());
test = test.addMonths(1); test = test.addMonths(1);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(!test.isDaylightTime());
QCOMPARE(test.date(), QDate(2011, 11, 30)); QCOMPARE(test.date(), QDate(2011, 11, 30));
QCOMPARE(test.time(), QTime(2, 0)); QCOMPARE(test.time(), QTime(2, 0));
QCOMPARE(test, QDateTime(QDate(2011, 11, 30), QTime(2, 0)));
// Add month to after tran FirstOccurrence // Add month to after after second pass (unambiguous)
test = QDateTime(QDate(2011, 10, 30), QTime(3, 0)); test = QDateTime(QDate(2011, 10, 30), QTime(3, 0));
QVERIFY(!test.isDaylightTime());
test = test.addMonths(1); test = test.addMonths(1);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(!test.isDaylightTime());
QCOMPARE(test.date(), QDate(2011, 11, 30)); QCOMPARE(test.date(), QDate(2011, 11, 30));
QCOMPARE(test.time(), QTime(3, 0)); QCOMPARE(test.time(), QTime(3, 0));
QCOMPARE(test, QDateTime(QDate(2011, 11, 30), QTime(3, 0)));
// Add day to get to tran FirstOccurrence // Add day to get to start of first pass
test = QDateTime(QDate(2012, 10, 27), QTime(2, 0)); test = QDateTime(QDate(2012, 10, 27), QTime(2, 0));
QVERIFY(test.isDaylightTime());
test = test.addDays(1); test = test.addDays(1);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(test.isDaylightTime());
QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.date(), QDate(2012, 10, 28));
QCOMPARE(test.time(), QTime(2, 0)); QCOMPARE(test.time(), QTime(2, 0));
#ifdef Q_OS_WIN // QCOMPARE(test, QDateTime(QDate(2012, 10, 28), QTime(2, 0), Prior));
// Windows uses SecondOccurrence QCOMPARE(test.toMSecsSinceEpoch(), autumn2012 - msecsOneHour);
QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue);
#endif // Q_OS_WIN
QCOMPARE(test.toMSecsSinceEpoch(), standard2012 - msecsOneHour);
// Add day to get to after tran FirstOccurrence // Add day to get to after second pass (unambiguous)
test = QDateTime(QDate(2012, 10, 27), QTime(3, 0)); test = QDateTime(QDate(2012, 10, 27), QTime(3, 0));
QVERIFY(test.isDaylightTime());
test = test.addDays(1); test = test.addDays(1);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(!test.isDaylightTime());
QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.date(), QDate(2012, 10, 28));
QCOMPARE(test.time(), QTime(3, 0)); QCOMPARE(test.time(), QTime(3, 0));
QCOMPARE(test.toMSecsSinceEpoch(), standard2012 + msecsOneHour); QCOMPARE(test, QDateTime(QDate(2012, 10, 28), QTime(3, 0)));
QCOMPARE(test.toMSecsSinceEpoch(), autumn2012 + msecsOneHour);
// Add day to tran FirstOccurrence // Add day to start of first pass
test = QDateTime(QDate(2011, 10, 30), QTime(2, 0)); test = QDateTime(QDate(2011, 10, 30), QTime(1, 0)).addMSecs(msecsOneHour);
QVERIFY(test.isDaylightTime());
test = test.addDays(1); test = test.addDays(1);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(!test.isDaylightTime());
QCOMPARE(test.date(), QDate(2011, 10, 31)); QCOMPARE(test.date(), QDate(2011, 10, 31));
QCOMPARE(test.time(), QTime(2, 0)); QCOMPARE(test.time(), QTime(2, 0));
QCOMPARE(test, QDateTime(QDate(2011, 10, 31), QTime(2, 0)));
// Add day to tran SecondOccurrence // Add day to start of second pass
test = QDateTime(QDate(2011, 10, 30), QTime(2, 0)); // TODO SecondOccurrence test = QDateTime(QDate(2011, 10, 30), QTime(3, 0)).addMSecs(-msecsOneHour);
QVERIFY(!test.isDaylightTime());
test = test.addDays(1); test = test.addDays(1);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(!test.isDaylightTime());
QCOMPARE(test.date(), QDate(2011, 10, 31)); QCOMPARE(test.date(), QDate(2011, 10, 31));
QCOMPARE(test.time(), QTime(2, 0)); QCOMPARE(test.time(), QTime(2, 0));
QCOMPARE(test, QDateTime(QDate(2011, 10, 31), QTime(2, 0)));
// Add day to after tran FirstOccurrence // Add day to after second pass (unambiguous)
test = QDateTime(QDate(2011, 10, 30), QTime(3, 0)); test = QDateTime(QDate(2011, 10, 30), QTime(3, 0));
QVERIFY(!test.isDaylightTime());
test = test.addDays(1); test = test.addDays(1);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(!test.isDaylightTime());
QCOMPARE(test.date(), QDate(2011, 10, 31)); QCOMPARE(test.date(), QDate(2011, 10, 31));
QCOMPARE(test.time(), QTime(3, 0)); QCOMPARE(test.time(), QTime(3, 0));
QCOMPARE(test, QDateTime(QDate(2011, 10, 31), QTime(3, 0)));
// Add hour to get to tran FirstOccurrence // Add hour to get to start of first pass
test = QDateTime(QDate(2012, 10, 28), QTime(1, 0)); test = QDateTime(QDate(2012, 10, 28), QTime(1, 0));
QVERIFY(test.isDaylightTime());
test = test.addMSecs(msecsOneHour); test = test.addMSecs(msecsOneHour);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(test.isDaylightTime());
QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.date(), QDate(2012, 10, 28));
QCOMPARE(test.time(), QTime(2, 0)); QCOMPARE(test.time(), QTime(2, 0));
QCOMPARE(test.toMSecsSinceEpoch(), standard2012 - msecsOneHour); // QCOMPARE(test, QDateTime(QDate(2012, 10, 28), QTime(2, 0), Prior));
QCOMPARE(test.toMSecsSinceEpoch(), autumn2012 - msecsOneHour);
// Add hour to tran FirstOccurrence to get to tran SecondOccurrence // Add hour to start of first pass to get to start of second pass
test = QDateTime(QDate(2012, 10, 28), QTime(2, 0));
test = test.addMSecs(msecsOneHour); test = test.addMSecs(msecsOneHour);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(!test.isDaylightTime());
QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.date(), QDate(2012, 10, 28));
#ifdef Q_OS_WIN
// Windows uses SecondOccurrence
QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue);
#endif // Q_OS_WIN
QCOMPARE(test.time(), QTime(2, 0)); QCOMPARE(test.time(), QTime(2, 0));
#ifdef Q_OS_WIN // QCOMPARE(test, QDateTime(QDate(2012, 10, 28), QTime(2, 0), Post));
// Windows uses SecondOccurrence QCOMPARE(test.toMSecsSinceEpoch(), autumn2012);
QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue);
#endif // Q_OS_WIN
QCOMPARE(test.toMSecsSinceEpoch(), standard2012);
// Add hour to tran SecondOccurrence to get to after tran FirstOccurrence // Add hour to start of second pass to get to after second pass
test = QDateTime(QDate(2012, 10, 28), QTime(2, 0)); // TODO SecondOccurrence
test = test.addMSecs(msecsOneHour); test = test.addMSecs(msecsOneHour);
QVERIFY(test.isValid()); QVERIFY(test.isValid());
QVERIFY(!test.isDaylightTime());
QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.date(), QDate(2012, 10, 28));
#if defined(Q_OS_DARWIN) || defined(Q_OS_QNX) || defined(Q_OS_ANDROID)
// 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)); QCOMPARE(test.time(), QTime(3, 0));
#if defined(Q_OS_DARWIN) || defined(Q_OS_QNX) || defined(Q_OS_ANDROID) QCOMPARE(test, QDateTime(QDate(2012, 10, 28), QTime(3, 0)));
// Mac uses FirstOccurrence, Windows uses SecondOccurrence, Linux uses last calculation QCOMPARE(test.toMSecsSinceEpoch(), autumn2012 + msecsOneHour);
QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue);
#endif // Q_OS_WIN
QCOMPARE(test.toMSecsSinceEpoch(), standard2012 + msecsOneHour);
} }
void tst_QDateTime::timeZones() const void tst_QDateTime::timeZones() const
@ -3764,85 +3796,93 @@ void tst_QDateTime::timeZones() const
QTimeZone cet("Europe/Oslo"); QTimeZone cet("Europe/Oslo");
// Standard Time to Daylight Time 2013 on 2013-03-31 is 2:00 local time / 1:00 UTC // Standard Time to Daylight Time 2013 on 2013-03-31 is 2:00 local time / 1:00 UTC
qint64 stdToDstMSecs = 1364691600000; const qint64 gapMSecs = 1364691600000;
QCOMPARE(gapMSecs, QDateTime(QDate(2013, 3, 31), QTime(1, 0), Qt::UTC).toMSecsSinceEpoch());
// Test MSecs to local // Test MSecs to local
// - Test 1 msec before tran = 01:59:59.999 // - Test 1 msec before tran = 01:59:59.999
QDateTime beforeDst = QDateTime::fromMSecsSinceEpoch(stdToDstMSecs - 1, cet); QDateTime beforeGap = QDateTime::fromMSecsSinceEpoch(gapMSecs - 1, cet);
QCOMPARE(beforeDst.date(), QDate(2013, 3, 31)); QCOMPARE(beforeGap.date(), QDate(2013, 3, 31));
QCOMPARE(beforeDst.time(), QTime(1, 59, 59, 999)); QCOMPARE(beforeGap.time(), QTime(1, 59, 59, 999));
// - Test at tran = 03:00:00 // - Test at tran = 03:00:00
QDateTime atDst = QDateTime::fromMSecsSinceEpoch(stdToDstMSecs, cet); QDateTime atGap = QDateTime::fromMSecsSinceEpoch(gapMSecs, cet);
QCOMPARE(atDst.date(), QDate(2013, 3, 31)); QCOMPARE(atGap.date(), QDate(2013, 3, 31));
QCOMPARE(atDst.time(), QTime(3, 0)); QCOMPARE(atGap.time(), QTime(3, 0));
// Test local to MSecs // Test local to MSecs
// - Test 1 msec before tran = 01:59:59.999 // - Test 1 msec before tran = 01:59:59.999
beforeDst = QDateTime(QDate(2013, 3, 31), QTime(1, 59, 59, 999), cet); beforeGap = QDateTime(QDate(2013, 3, 31), QTime(1, 59, 59, 999), cet);
QCOMPARE(beforeDst.toMSecsSinceEpoch(), stdToDstMSecs - 1); QCOMPARE(beforeGap.toMSecsSinceEpoch(), gapMSecs - 1);
// - Test at tran = 03:00:00 // - Test at tran = 03:00:00
atDst = QDateTime(QDate(2013, 3, 31), QTime(3, 0), cet); atGap = QDateTime(QDate(2013, 3, 31), QTime(3, 0), cet);
QCOMPARE(atDst.toMSecsSinceEpoch(), stdToDstMSecs); QCOMPARE(atGap.toMSecsSinceEpoch(), gapMSecs);
// - Test transition hole, setting 03:00:00 is valid // - Test transition hole, setting 03:00:00 is valid
atDst = QDateTime(QDate(2013, 3, 31), QTime(3, 0), cet); atGap = QDateTime(QDate(2013, 3, 31), QTime(3, 0), cet);
QVERIFY(atDst.isValid()); QVERIFY(atGap.isValid());
QCOMPARE(atDst.date(), QDate(2013, 3, 31)); QCOMPARE(atGap.date(), QDate(2013, 3, 31));
QCOMPARE(atDst.time(), QTime(3, 0)); QCOMPARE(atGap.time(), QTime(3, 0));
QCOMPARE(atDst.toMSecsSinceEpoch(), stdToDstMSecs); QCOMPARE(atGap.toMSecsSinceEpoch(), gapMSecs);
// - Test transition hole, setting 02:00:00 is invalid // - Test transition hole, setting 02:00:00 is invalid
atDst = QDateTime(QDate(2013, 3, 31), QTime(2, 0), cet); QDateTime inGap = QDateTime(QDate(2013, 3, 31), QTime(2, 0), cet);
QVERIFY(!atDst.isValid()); QVERIFY(!inGap.isValid());
QCOMPARE(atDst.date(), QDate(2013, 3, 31)); QCOMPARE(inGap.date(), QDate(2013, 3, 31));
QCOMPARE(atDst.time(), QTime(2, 0)); QCOMPARE(inGap.time(), QTime(2, 0));
// - Test transition hole, setting 02:59:59.999 is invalid // - Test transition hole, setting 02:59:59.999 is invalid
atDst = QDateTime(QDate(2013, 3, 31), QTime(2, 59, 59, 999), cet); inGap = QDateTime(QDate(2013, 3, 31), QTime(2, 59, 59, 999), cet);
QVERIFY(!atDst.isValid()); QVERIFY(!inGap.isValid());
QCOMPARE(atDst.date(), QDate(2013, 3, 31)); QCOMPARE(inGap.date(), QDate(2013, 3, 31));
QCOMPARE(atDst.time(), QTime(2, 59, 59, 999)); QCOMPARE(inGap.time(), QTime(2, 59, 59, 999));
// Standard Time to Daylight Time 2013 on 2013-10-27 is 3:00 local time / 1:00 UTC // Standard Time to Daylight Time 2013 on 2013-10-27 is 3:00 local time / 1:00 UTC
qint64 dstToStdMSecs = 1382835600000; const qint64 replayMSecs = 1382835600000;
QCOMPARE(replayMSecs, QDateTime(QDate(2013, 10, 27), QTime(1, 0), Qt::UTC).toMSecsSinceEpoch());
// Test MSecs to local // Test MSecs to local
// - Test 1 hour before tran = 02:00:00 local first occurrence // - Test 1 hour before tran = 02:00:00 local first occurrence
QDateTime hourBeforeStd = QDateTime::fromMSecsSinceEpoch(dstToStdMSecs - 3600000, cet); QDateTime startFirst = QDateTime::fromMSecsSinceEpoch(replayMSecs - 3600000, cet);
QCOMPARE(hourBeforeStd.date(), QDate(2013, 10, 27)); QCOMPARE(startFirst.date(), QDate(2013, 10, 27));
QCOMPARE(hourBeforeStd.time(), QTime(2, 0)); QCOMPARE(startFirst.time(), QTime(2, 0));
// - Test 1 msec before tran = 02:59:59.999 local first occurrence // - Test 1 msec before tran = 02:59:59.999 local first occurrence
QDateTime msecBeforeStd = QDateTime::fromMSecsSinceEpoch(dstToStdMSecs - 1, cet); QDateTime endFirst = QDateTime::fromMSecsSinceEpoch(replayMSecs - 1, cet);
QCOMPARE(msecBeforeStd.date(), QDate(2013, 10, 27)); QCOMPARE(endFirst.date(), QDate(2013, 10, 27));
QCOMPARE(msecBeforeStd.time(), QTime(2, 59, 59, 999)); QCOMPARE(endFirst.time(), QTime(2, 59, 59, 999));
// - Test at tran = 03:00:00 local becomes 02:00:00 local second occurrence // - Test at tran = 03:00:00 local becomes 02:00:00 local second occurrence
QDateTime atStd = QDateTime::fromMSecsSinceEpoch(dstToStdMSecs, cet); QDateTime startRepeat = QDateTime::fromMSecsSinceEpoch(replayMSecs, cet);
QCOMPARE(atStd.date(), QDate(2013, 10, 27)); QCOMPARE(startRepeat.date(), QDate(2013, 10, 27));
QCOMPARE(atStd.time(), QTime(2, 0)); QCOMPARE(startRepeat.time(), QTime(2, 0));
// - Test 59 mins after tran = 02:59:59.999 local second occurrence // - Test 59 mins after tran = 02:59:59.999 local second occurrence
QDateTime afterStd = QDateTime::fromMSecsSinceEpoch(dstToStdMSecs + 3600000 -1, cet); QDateTime endRepeat = QDateTime::fromMSecsSinceEpoch(replayMSecs + 3600000 -1, cet);
QCOMPARE(afterStd.date(), QDate(2013, 10, 27)); QCOMPARE(endRepeat.date(), QDate(2013, 10, 27));
QCOMPARE(afterStd.time(), QTime(2, 59, 59, 999)); QCOMPARE(endRepeat.time(), QTime(2, 59, 59, 999));
// - Test 1 hour after tran = 03:00:00 local // - Test 1 hour after tran = 03:00:00 local
QDateTime hourAfterStd = QDateTime::fromMSecsSinceEpoch(dstToStdMSecs + 3600000, cet); QDateTime hourAfter = QDateTime::fromMSecsSinceEpoch(replayMSecs + 3600000, cet);
QCOMPARE(hourAfterStd.date(), QDate(2013, 10, 27)); QCOMPARE(hourAfter.date(), QDate(2013, 10, 27));
QCOMPARE(hourAfterStd.time(), QTime(3, 00, 00)); QCOMPARE(hourAfter.time(), QTime(3, 0, 0));
// TODO (QTBUG-79923): Compare to results of direct QDateTime(date, time, cet, fold)
// construction; see Prior/Post commented-out tests.
// Test local to MSecs // Test local to MSecs
// - Test first occurrence 02:00:00 = 1 hour before tran // - Test first occurrence 02:00:00 = 1 hour before tran
hourBeforeStd = QDateTime(QDate(2013, 10, 27), QTime(2, 0), cet); startFirst = QDateTime(QDate(2013, 10, 27), QTime(1, 59, 59), cet).addSecs(1);
QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); // QCOMPARE(startFirst, QDateTime(QDate(2013, 10, 27), QTime(2, 0), cet, Prior));
QCOMPARE(hourBeforeStd.toMSecsSinceEpoch(), dstToStdMSecs - 3600000); QCOMPARE(startFirst.toMSecsSinceEpoch(), replayMSecs - 3600000);
// - Test first occurrence 02:59:59.999 = 1 msec before tran // - Test first occurrence 02:59:59.999 = 1 msec before tran
msecBeforeStd = QDateTime(QDate(2013, 10, 27), QTime(2, 59, 59, 999), cet); endFirst = startFirst.addMSecs(3599999);
QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); // QCOMPARE(endFirst, QDateTime(QDate(2013, 10, 27), QTime(2, 59, 59, 999), cet, Prior));
QCOMPARE(msecBeforeStd.toMSecsSinceEpoch(), dstToStdMSecs - 1); QCOMPARE(endFirst.toMSecsSinceEpoch(), replayMSecs - 1);
// - Test second occurrence 02:00:00 = at tran // - Test second occurrence 02:00:00 = at tran
atStd = QDateTime(QDate(2013, 10, 27), QTime(2, 0), cet); startRepeat = endFirst.addMSecs(1);
QCOMPARE(atStd.toMSecsSinceEpoch(), dstToStdMSecs); // QCOMPARE(startRepeat, QDateTime(QDate(2013, 10, 27), QTime(2, 0), cet, Post));
// - Test second occurrence 03:00:00 = 59 mins after tran QCOMPARE(startRepeat.toMSecsSinceEpoch(), replayMSecs);
afterStd = QDateTime(QDate(2013, 10, 27), QTime(2, 59, 59, 999), cet); // - Test second occurrence 02:59:59.999 = 1 msec before 1 hour after tran
QCOMPARE(afterStd.toMSecsSinceEpoch(), dstToStdMSecs + 3600000 - 1); endRepeat = startRepeat.addMSecs(3599999);
// - Test 03:00:00 = 1 hour after tran // QCOMPARE(endRepeat, QDateTime(QDate(2013, 10, 27), QTime(2, 59, 59, 999), cet, Post));
hourAfterStd = QDateTime(QDate(2013, 10, 27), QTime(3, 0), cet); QCOMPARE(endRepeat.toMSecsSinceEpoch(), replayMSecs + 3600000 - 1);
QCOMPARE(hourAfterStd.toMSecsSinceEpoch(), dstToStdMSecs + 3600000); // - Test 03:00:00 = 1 hour after tran (no ambiguity)
hourAfter = endRepeat.addMSecs(1);
QCOMPARE(hourAfter, QDateTime(QDate(2013, 10, 27), QTime(3, 0), cet));
QCOMPARE(hourAfter.toMSecsSinceEpoch(), replayMSecs + 3600000);
// Test Time Zone that has transitions but no future transitions afer a given date // Test Time Zone that has transitions but no future transitions afer a given date
QTimeZone sgt("Asia/Singapore"); QTimeZone sgt("Asia/Singapore");