summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/tools/qdatetime
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/tools/qdatetime')
-rw-r--r--tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp187
1 files changed, 133 insertions, 54 deletions
diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
index 0088820b41..4f82ce9c08 100644
--- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
+++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
@@ -155,7 +155,7 @@ private slots:
private:
enum { LocalTimeIsUtc = 0, LocalTimeAheadOfUtc = 1, LocalTimeBehindUtc = -1} localTimeType;
- bool europeanTimeZone;
+ bool zoneIsCET;
QDate defDate() const { return QDate(1900, 1, 1); }
QTime defTime() const { return QTime(0, 0, 0); }
QDateTime defDateTime() const { return QDateTime(defDate(), defTime()); }
@@ -171,21 +171,70 @@ Q_DECLARE_METATYPE(Qt::DateFormat)
tst_QDateTime::tst_QDateTime()
{
- uint x1 = QDateTime(QDate(1990, 1, 1), QTime()).toTime_t();
- uint x2 = QDateTime(QDate(1990, 6, 1), QTime()).toTime_t();
- europeanTimeZone = (x1 == 631148400 && x2 == 644191200);
-
- QDateTime dt1 = QDateTime::fromTime_t(0);
- QDateTime dt2 = QDateTime::fromTime_t(181 * 86400); // six months later, Jul 1
- if (dt1.date().year() < 1970 || dt2.date().month() < 7) {
- localTimeType = LocalTimeBehindUtc;
- } else if (dt1.time().hour() > 0 || dt1.date().day() > 1) {
- localTimeType = LocalTimeAheadOfUtc;
- } else if (dt2.time().hour() > 0 || dt2.date().day() > 1) {
- localTimeType = LocalTimeAheadOfUtc;
- } else {
- localTimeType = LocalTimeIsUtc;
+ /*
+ Due to some jurisdictions changing their zones and rules, it's possible
+ for a non-CET zone to accidentally match CET at a few tested moments but
+ be different a few years later or earlier. This would lead to tests
+ failing if run in the partially-aliasing zone (e.g. Algeria, Lybia). So
+ test thoroughly; ideally at every mid-winter or mid-summer in whose
+ half-year any test below assumes zoneIsCET means what it says. (Tests at
+ or near a DST transition implicate both of the half-years that meet
+ there.) Years outside the 1970--2038 range, however, are likely not
+ properly handled by the TZ-database; and QDateTime explicitly handles them
+ differently, so don't probe them here.
+ */
+ const uint day = 24 * 3600; // in seconds
+ zoneIsCET = (QDateTime(QDate(2038, 1, 19), QTime(4, 14, 7)).toTime_t() == 0x7fffffff
+ // Entries a year apart robustly differ by multiples of day.
+ && QDateTime(QDate(2015, 7, 1), QTime()).toTime_t() == 1435701600
+ && QDateTime(QDate(2015, 1, 1), QTime()).toTime_t() == 1420066800
+ && QDateTime(QDate(2013, 7, 1), QTime()).toTime_t() == 1372629600
+ && QDateTime(QDate(2013, 1, 1), QTime()).toTime_t() == 1356994800
+ && QDateTime(QDate(2012, 7, 1), QTime()).toTime_t() == 1341093600
+ && QDateTime(QDate(2012, 1, 1), QTime()).toTime_t() == 1325372400
+ && QDateTime(QDate(2008, 7, 1), QTime()).toTime_t() == 1214863200
+ && QDateTime(QDate(2004, 1, 1), QTime()).toTime_t() == 1072911600
+ && QDateTime(QDate(2000, 1, 1), QTime()).toTime_t() == 946681200
+ && QDateTime(QDate(1990, 7, 1), QTime()).toTime_t() == 646783200
+ && QDateTime(QDate(1990, 1, 1), QTime()).toTime_t() == 631148400
+ && QDateTime(QDate(1979, 1, 1), QTime()).toTime_t() == 283993200
+ // .toTime_t() returns -1 for everything before this:
+ && QDateTime(QDate(1970, 1, 1), QTime(1, 0, 0)).toTime_t() == 0);
+ // Use .toMSecsSinceEpoch() if you really need to test anything earlier.
+
+ /*
+ Again, rule changes can cause a TZ to look like UTC at some sample dates
+ but deviate at some date relevant to a test using localTimeType. These
+ tests mostly use years outside the 1970--2038 range for which TZ data is
+ credible, so we can't helpfully be exhaustive. So scan a sample of years'
+ starts and middles.
+ */
+ const int sampled = 3;
+ // UTC starts of months in 2004, 2038 and 1970:
+ uint jans[sampled] = { 12418 * day, 24837 * day, 0 };
+ uint juls[sampled] = { 12600 * day, 25018 * day, 181 * day };
+ localTimeType = LocalTimeIsUtc;
+ for (int i = sampled; i-- > 0; ) {
+ QDateTime jan = QDateTime::fromTime_t(jans[i]);
+ QDateTime jul = QDateTime::fromTime_t(juls[i]);
+ if (jan.date().year() < 1970 || jul.date().month() < 7) {
+ localTimeType = LocalTimeBehindUtc;
+ break;
+ } else if (jan.time().hour() > 0 || jul.time().hour() > 0
+ || jan.date().day() > 1 || jul.date().day() > 1) {
+ localTimeType = LocalTimeAheadOfUtc;
+ break;
+ }
}
+ /*
+ Even so, TZ=Africa/Algiers will fail fromMSecsSinceEpoch(-1) because it
+ switched from WET without DST (i.e. UTC) in the late 1960s to WET with DST
+ for all of 1970 - so they had a DST transition *on the epoch*. They've
+ since switched to CET with no DST, making life simple; but our tests for
+ mistakes around the epoch can't tell the difference between what Algeria
+ really did and the symptoms we can believe a bug might produce: there's
+ not much we can do about that, that wouldn't hide real bugs.
+ */
}
void tst_QDateTime::initTestCase()
@@ -201,7 +250,7 @@ void tst_QDateTime::initTestCase()
break;
case LocalTimeAheadOfUtc:
typemsg1 = "ahead of";
- typemsg2 = europeanTimeZone ? "and is" : "but isn't";
+ typemsg2 = zoneIsCET ? "and is" : "but isn't";
break;
}
@@ -245,7 +294,7 @@ void tst_QDateTime::ctor()
QCOMPARE(dt3.timeSpec(), Qt::UTC);
QVERIFY(dt1 == dt2);
- if (europeanTimeZone) {
+ if (zoneIsCET) {
QVERIFY(dt1 != dt3);
QVERIFY(dt1 < dt3);
QVERIFY(dt1.addSecs(3600).toUTC() == dt3);
@@ -492,7 +541,7 @@ void tst_QDateTime::setTime_t()
dt1.setTime_t(123456);
QCOMPARE(dt1, QDateTime(QDate(1970, 1, 2), QTime(10, 17, 36), Qt::UTC));
- if (europeanTimeZone) {
+ if (zoneIsCET) {
QDateTime dt2;
dt2.setTime_t(123456);
QCOMPARE(dt2, QDateTime(QDate(1970, 1, 2), QTime(11, 17, 36), Qt::LocalTime));
@@ -500,7 +549,7 @@ void tst_QDateTime::setTime_t()
dt1.setTime_t((uint)(quint32)-123456);
QCOMPARE(dt1, QDateTime(QDate(2106, 2, 5), QTime(20, 10, 40), Qt::UTC));
- if (europeanTimeZone) {
+ if (zoneIsCET) {
QDateTime dt2;
dt2.setTime_t((uint)(quint32)-123456);
QCOMPARE(dt2, QDateTime(QDate(2106, 2, 5), QTime(21, 10, 40), Qt::LocalTime));
@@ -508,7 +557,7 @@ void tst_QDateTime::setTime_t()
dt1.setTime_t(1214567890);
QCOMPARE(dt1, QDateTime(QDate(2008, 6, 27), QTime(11, 58, 10), Qt::UTC));
- if (europeanTimeZone) {
+ if (zoneIsCET) {
QDateTime dt2;
dt2.setTime_t(1214567890);
QCOMPARE(dt2, QDateTime(QDate(2008, 6, 27), QTime(13, 58, 10), Qt::LocalTime));
@@ -516,7 +565,7 @@ void tst_QDateTime::setTime_t()
dt1.setTime_t(0x7FFFFFFF);
QCOMPARE(dt1, QDateTime(QDate(2038, 1, 19), QTime(3, 14, 7), Qt::UTC));
- if (europeanTimeZone) {
+ if (zoneIsCET) {
QDateTime dt2;
dt2.setTime_t(0x7FFFFFFF);
QCOMPARE(dt2, QDateTime(QDate(2038, 1, 19), QTime(4, 14, 7), Qt::LocalTime));
@@ -533,7 +582,7 @@ void tst_QDateTime::setMSecsSinceEpoch_data()
{
QTest::addColumn<qint64>("msecs");
QTest::addColumn<QDateTime>("utc");
- QTest::addColumn<QDateTime>("european");
+ QTest::addColumn<QDateTime>("cet");
QTest::newRow("zero")
<< Q_INT64_C(0)
@@ -584,7 +633,7 @@ void tst_QDateTime::setMSecsSinceEpoch()
{
QFETCH(qint64, msecs);
QFETCH(QDateTime, utc);
- QFETCH(QDateTime, european);
+ QFETCH(QDateTime, cet);
QDateTime dt;
dt.setTimeSpec(Qt::UTC);
@@ -595,8 +644,8 @@ void tst_QDateTime::setMSecsSinceEpoch()
QCOMPARE(dt.time(), utc.time());
QCOMPARE(dt.timeSpec(), Qt::UTC);
- if (europeanTimeZone) {
- QCOMPARE(dt.toLocalTime(), european);
+ if (zoneIsCET) {
+ QCOMPARE(dt.toLocalTime(), cet);
// Test converting from LocalTime to UTC back to LocalTime.
QDateTime localDt;
@@ -613,13 +662,13 @@ void tst_QDateTime::setMSecsSinceEpoch()
QDateTime dt2;
dt2.setTimeZone(europe);
dt2.setMSecsSinceEpoch(msecs);
- QCOMPARE(dt2.date(), european.date());
+ QCOMPARE(dt2.date(), cet.date());
// don't compare the time if the date is too early or too late: prior
// to 1916, timezones in Europe were not standardised and some OS APIs
// have hard limits. Let's restrict it to the 32-bit Unix range
if (dt2.date().year() >= 1970 && dt2.date().year() <= 2037)
- QCOMPARE(dt2.time(), european.time());
+ QCOMPARE(dt2.time(), cet.time());
QCOMPARE(dt2.timeSpec(), Qt::TimeZone);
QCOMPARE(dt2.timeZone(), europe);
}
@@ -643,7 +692,7 @@ void tst_QDateTime::fromMSecsSinceEpoch()
{
QFETCH(qint64, msecs);
QFETCH(QDateTime, utc);
- QFETCH(QDateTime, european);
+ QFETCH(QDateTime, cet);
QDateTime dtLocal = QDateTime::fromMSecsSinceEpoch(msecs, Qt::LocalTime);
QDateTime dtUtc = QDateTime::fromMSecsSinceEpoch(msecs, Qt::UTC);
@@ -665,10 +714,10 @@ void tst_QDateTime::fromMSecsSinceEpoch()
if (msecs != std::numeric_limits<qint64>::max())
QCOMPARE(dtOffset.time(), utc.time().addMSecs(60*60*1000));
- if (europeanTimeZone) {
- QCOMPARE(dtLocal.toLocalTime(), european);
- QCOMPARE(dtUtc.toLocalTime(), european);
- QCOMPARE(dtOffset.toLocalTime(), european);
+ if (zoneIsCET) {
+ QCOMPARE(dtLocal.toLocalTime(), cet);
+ QCOMPARE(dtUtc.toLocalTime(), cet);
+ QCOMPARE(dtOffset.toLocalTime(), cet);
} else {
QSKIP("You must test using Central European (CET/CEST) time zone, e.g. TZ=Europe/Oslo");
}
@@ -793,7 +842,7 @@ void tst_QDateTime::toString_rfcDate_data()
QTest::addColumn<QDateTime>("dt");
QTest::addColumn<QString>("formatted");
- if (europeanTimeZone) {
+ if (zoneIsCET) {
QTest::newRow("localtime")
<< QDateTime(QDate(1978, 11, 9), QTime(13, 28, 34))
<< QString("09 Nov 1978 13:28:34 +0100");
@@ -1050,7 +1099,7 @@ void tst_QDateTime::addSecs_data()
QTest::newRow("utc9") << QDateTime(QDate(4000, 1, 1), standardTime, Qt::UTC) << 0
<< QDateTime(QDate(4000, 1, 1), standardTime, Qt::UTC);
- if (europeanTimeZone) {
+ if (zoneIsCET) {
QTest::newRow("cet0") << QDateTime(QDate(2004, 1, 1), standardTime, Qt::LocalTime) << 86400
<< QDateTime(QDate(2004, 1, 2), standardTime, Qt::LocalTime);
QTest::newRow("cet1") << QDateTime(QDate(2004, 1, 1), standardTime, Qt::LocalTime) << (86400 * 185)
@@ -1162,7 +1211,7 @@ void tst_QDateTime::toTimeSpec_data()
<< QDateTime(QDate(-271821, 4, 20), QTime(23, 0, 0), Qt::UTC)
<< QDateTime(QDate(-271821, 4, 21), QTime(0, 0, 0), Qt::LocalTime);
- if (europeanTimeZone) {
+ if (zoneIsCET) {
QTest::newRow("summer1") << QDateTime(QDate(2004, 6, 30), utcTime, Qt::UTC)
<< QDateTime(QDate(2004, 6, 30), localDaylightTime, Qt::LocalTime);
QTest::newRow("summer2") << QDateTime(QDate(1760, 6, 30), utcTime, Qt::UTC)
@@ -1185,7 +1234,7 @@ void tst_QDateTime::toTimeSpec_data()
void tst_QDateTime::toTimeSpec()
{
- if (europeanTimeZone) {
+ if (zoneIsCET) {
QFETCH(QDateTime, fromUtc);
QFETCH(QDateTime, fromLocal);
@@ -1240,7 +1289,7 @@ void tst_QDateTime::toTimeSpec()
QCOMPARE(localToOffset.time(), fromUtc.time());
QCOMPARE(localToOffset.timeSpec(), Qt::UTC);
} else {
- QSKIP("Not tested with timezone other than Central European (CET/CST)");
+ QSKIP("Not tested with timezone other than Central European (CET/CEST)");
}
}
@@ -1251,7 +1300,7 @@ void tst_QDateTime::toLocalTime_data()
void tst_QDateTime::toLocalTime()
{
- if (europeanTimeZone) {
+ if (zoneIsCET) {
QFETCH(QDateTime, fromUtc);
QFETCH(QDateTime, fromLocal);
@@ -1262,7 +1311,7 @@ void tst_QDateTime::toLocalTime()
QCOMPARE(fromUtc.toLocalTime(), fromLocal);
QCOMPARE(fromUtc.toLocalTime(), fromLocal.toLocalTime());
} else {
- QSKIP("Not tested with timezone other than Central European (CET/CST)");
+ QSKIP("Not tested with timezone other than Central European (CET/CEST)");
}
}
@@ -1273,7 +1322,7 @@ void tst_QDateTime::toUTC_data()
void tst_QDateTime::toUTC()
{
- if (europeanTimeZone) {
+ if (zoneIsCET) {
QFETCH(QDateTime, fromUtc);
QFETCH(QDateTime, fromLocal);
@@ -1284,7 +1333,7 @@ void tst_QDateTime::toUTC()
QCOMPARE(fromLocal.toUTC(), fromUtc);
QCOMPARE(fromUtc.toUTC(), fromLocal.toUTC());
} else {
- QSKIP("Not tested with timezone other than Central European (CET/CST)");
+ QSKIP("Not tested with timezone other than Central European (CET/CEST)");
}
QDateTime dt = QDateTime::currentDateTime();
@@ -1614,14 +1663,44 @@ void tst_QDateTime::springForward_data()
QTest::addColumn<int>("step"); // days to step; +ve from before, -ve from after
QTest::addColumn<int>("adjust"); // minutes ahead of UTC on day stepped from
- if (europeanTimeZone) {
- QTest::newRow("Europe from day before") << QDate(2015, 3, 29) << QTime(2, 30, 0) << 1 << 60;
-#if 0 // FIXME: fails
- QTest::newRow("Europe from day after") << QDate(2015, 3, 29) << QTime(2, 30, 0) << -1 << 120;
-#endif
- // } else if (otherZone) {
+ /*
+ Zone tests compare a summer and winter moment's time_t to known values.
+ This could in principle be flawed (two DST-using zones in the same
+ hemisphere with the same DST and standard times but different transition
+ times) but no actual example is known where this is a problem. Please
+ document any such conflicts, if discovered.
+
+ See http://www.timeanddate.com/time/zones/ for data on more candidates to
+ test.
+ */
+
+ uint winter = QDateTime(QDate(2015, 1, 1), QTime()).toTime_t();
+ uint summer = QDateTime(QDate(2015, 7, 1), QTime()).toTime_t();
+
+ if (winter == 1420066800 && summer == 1435701600) {
+ QTest::newRow("CET from day before") << QDate(2015, 3, 29) << QTime(2, 30, 0) << 1 << 60;
+ QTest::newRow("CET from day after") << QDate(2015, 3, 29) << QTime(2, 30, 0) << -1 << 120;
+ } else if (winter == 1420063200 && summer == 1435698000) {
+ // e.g. Finland, where our CI runs ...
+ QTest::newRow("EET from day before") << QDate(2015, 3, 29) << QTime(3, 30, 0) << 1 << 120;
+ QTest::newRow("EET from day after") << QDate(2015, 3, 29) << QTime(3, 30, 0) << -1 << 180;
+ } else if (winter == 1420070400 && summer == 1435705200) {
+ // Western European Time, WET/WEST; a.k.a. GMT/BST
+ QTest::newRow("WET from day before") << QDate(2015, 3, 29) << QTime(1, 30, 0) << 1 << 0;
+ QTest::newRow("WET from day after") << QDate(2015, 3, 29) << QTime(1, 30, 0) << -1 << 60;
+ } else if (winter == 1420099200 && summer == 1435734000) {
+ // Western USA, Canada: Pacific Time (e.g. US/Pacific)
+ QTest::newRow("PT from day before") << QDate(2015, 3, 8) << QTime(2, 30, 0) << 1 << -480;
+ QTest::newRow("PT from day after") << QDate(2015, 3, 8) << QTime(2, 30, 0) << -1 << -420;
+ } else if (winter == 1420088400 && summer == 1435723200) {
+ // Eastern USA, Canada: Eastern Time (e.g. US/Eastern)
+ QTest::newRow("ET from day before") << QDate(2015, 3, 8) << QTime(2, 30, 0) << 1 << -300;
+ QTest::newRow("ET from day after") << QDate(2015, 3, 8) << QTime(2, 30, 0) << -1 << -240;
} else {
- QSKIP("No spring forward test data for this TZ");
+ // Includes the numbers you need to test for your zone, as above:
+ QString msg(QString::fromLatin1("No spring forward test data for this TZ (%1, %2)"
+ ).arg(winter).arg(summer));
+ QSKIP(qPrintable(msg));
}
}
@@ -1689,7 +1768,7 @@ void tst_QDateTime::operator_eqeq_data()
QTest::newRow("invalid == invalid") << invalidDateTime() << invalidDateTime() << true << false;
QTest::newRow("invalid == valid #1") << invalidDateTime() << dateTime1 << false << false;
- if (europeanTimeZone) {
+ if (zoneIsCET) {
QTest::newRow("data14") << QDateTime(QDate(2004, 1, 2), QTime(2, 2, 3), Qt::LocalTime)
<< QDateTime(QDate(2004, 1, 2), QTime(1, 2, 3), Qt::UTC) << true << true;
}
@@ -1721,7 +1800,7 @@ void tst_QDateTime::operator_eqeq()
if (equal)
QVERIFY(qHash(dt1) == qHash(dt2));
- if (checkEuro && europeanTimeZone) {
+ if (checkEuro && zoneIsCET) {
QVERIFY(dt1.toUTC() == dt2);
QVERIFY(dt1 == dt2.toLocalTime());
}
@@ -2237,7 +2316,7 @@ void tst_QDateTime::offsetFromUtc()
QCOMPARE(dt2.offsetFromUtc(), 0);
// LocalTime should vary
- if (europeanTimeZone) {
+ if (zoneIsCET) {
// Time definitely in Standard Time so 1 hour ahead
QDateTime dt3(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::LocalTime);
QCOMPARE(dt3.offsetFromUtc(), 1 * 60 * 60);
@@ -2362,7 +2441,7 @@ void tst_QDateTime::timeZoneAbbreviation()
QCOMPARE(dt3.timeZoneAbbreviation(), QString("UTC"));
// LocalTime should vary
- if (europeanTimeZone) {
+ if (zoneIsCET) {
// Time definitely in Standard Time
QDateTime dt4(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::LocalTime);
#ifdef Q_OS_WIN
@@ -2486,7 +2565,7 @@ void tst_QDateTime::isDaylightTime() const
QDateTime offset2(QDate(2012, 6, 1), QTime(0, 0, 0), Qt::OffsetFromUTC, 1 * 60 * 60);
QVERIFY(!offset2.isDaylightTime());
- if (europeanTimeZone) {
+ if (zoneIsCET) {
QDateTime cet1(QDate(2012, 1, 1), QTime(0, 0, 0));
QVERIFY(!cet1.isDaylightTime());
QDateTime cet2(QDate(2012, 6, 1), QTime(0, 0, 0));
@@ -2498,7 +2577,7 @@ void tst_QDateTime::isDaylightTime() const
void tst_QDateTime::daylightTransitions() const
{
- if (europeanTimeZone) {
+ if (zoneIsCET) {
// CET transitions occur at 01:00:00 UTC on last Sunday in March and October
// 2011-03-27 02:00:00 CET became 03:00:00 CEST at msecs = 1301187600000
// 2011-10-30 03:00:00 CEST became 02:00:00 CET at msecs = 1319936400000