From 718a2251be2d32f96befef1ec23912c1a2ce3e34 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Thu, 16 Aug 2012 15:55:31 +0200 Subject: Serialise QDateTime as UTC and timeSpec() instead of private spec. QDateTime currently serialises its private Spec enum. If a user was to deserialise the individual components of a QDateTime separately, the resulting timeSpec may be invalid when cast to the Qt::TimeSpec enum. E.g.: QDateTime dateTime(QDate(2012, 8, 14), QTime(8, 0, 0), Qt::UTC); // ... serialise // ... deserialise date, time, spec separately. // spec == 2, the value of QDateTimePrivate::UTC. // spec != UTC, will be set to LocalUnknown. QDateTime deserialised(date, time, spec); This patch serialises QDateTime objects in UTC and the value of timeSpec() as opposed to QDateTimePrivate's spec. This changes the serialisation behaviour of QDateTime for version 13 of QDataStream. Task-number: QTBUG-4057 Change-Id: If650e7960dca7b6ab44b8233410a6369c41df73a Reviewed-by: Thiago Macieira --- .../auto/corelib/tools/qdatetime/tst_qdatetime.cpp | 76 ++++++++++++++++++++++ 1 file changed, 76 insertions(+) (limited to 'tests') diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index 6327e73ba5..70b761f705 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -106,6 +106,8 @@ private slots: void msecsTo(); void operator_eqeq_data(); void operator_eqeq(); + void operator_insert_extract_data(); + void operator_insert_extract(); void currentDateTime(); void currentDateTimeUtc(); void currentDateTimeUtc2(); @@ -1221,6 +1223,80 @@ void tst_QDateTime::operator_eqeq() } } +void tst_QDateTime::operator_insert_extract_data() +{ + QTest::addColumn("dateTime"); + QTest::addColumn("serialiseAs"); + QTest::addColumn("deserialiseAs"); + + const QDateTime positiveYear(QDateTime(QDate(2012, 8, 14), QTime(8, 0, 0), Qt::LocalTime)); + const QDateTime negativeYear(QDateTime(QDate(-2012, 8, 14), QTime(8, 0, 0), Qt::LocalTime)); + + const QString westernAustralia(QString::fromLatin1("AWST-8AWDT-9,M10.5.0,M3.5.0/03:00:00")); + const QString hawaii(QString::fromLatin1("HAW10")); + + QTest::newRow("14/08/2012 08:00 WA => HAWAII") << positiveYear << westernAustralia << hawaii; + QTest::newRow("14/08/2012 08:00 WA => HAWAII") << positiveYear << westernAustralia << hawaii; + QTest::newRow("14/08/2012 08:00 WA => HAWAII") << positiveYear << westernAustralia << hawaii; + QTest::newRow("14/08/2012 08:00 WA => WA") << positiveYear << westernAustralia << westernAustralia; + QTest::newRow("14/08/-2012 08:00 HAWAII => WA") << negativeYear << hawaii << westernAustralia; + QTest::newRow("14/08/-2012 08:00 HAWAII => WA") << negativeYear << hawaii << westernAustralia; + QTest::newRow("14/08/-2012 08:00 HAWAII => WA") << negativeYear << hawaii << westernAustralia; + QTest::newRow("14/08/2012 08:00 HAWAII => HAWAII") << positiveYear << hawaii << hawaii; +} + +void tst_QDateTime::operator_insert_extract() +{ + QFETCH(QDateTime, dateTime); + QFETCH(QString, serialiseAs); + QFETCH(QString, deserialiseAs); + + QString previousTimeZone = qgetenv("TZ"); + qputenv("TZ", serialiseAs.toLocal8Bit().constData()); + tzset(); + QDateTime dateTimeAsUTC(dateTime.toUTC()); + + QByteArray byteArray; + { + QDataStream dataStream(&byteArray, QIODevice::WriteOnly); + dataStream << dateTime; + dataStream << dateTime; + } + + // Ensure that a change in timezone between serialisation and deserialisation + // still results in identical UTC-converted datetimes. + qputenv("TZ", deserialiseAs.toLocal8Bit().constData()); + tzset(); + QDateTime expectedLocalTime(dateTimeAsUTC.toLocalTime()); + { + // Deserialise whole QDateTime at once. + QDataStream dataStream(&byteArray, QIODevice::ReadOnly); + QDateTime deserialised; + dataStream >> deserialised; + // Ensure local time is still correct. + QCOMPARE(deserialised, expectedLocalTime); + // Sanity check UTC times. + QCOMPARE(deserialised.toUTC(), expectedLocalTime.toUTC()); + + // Deserialise each component individually. + QDate deserialisedDate; + dataStream >> deserialisedDate; + QTime deserialisedTime; + dataStream >> deserialisedTime; + qint8 deserialisedSpec; + dataStream >> deserialisedSpec; + deserialised = QDateTime(deserialisedDate, deserialisedTime, Qt::UTC); + deserialised = deserialised.toTimeSpec(static_cast(deserialisedSpec)); + // Ensure local time is still correct. + QCOMPARE(deserialised, expectedLocalTime); + // Sanity check UTC times. + QCOMPARE(deserialised.toUTC(), expectedLocalTime.toUTC()); + } + + qputenv("TZ", previousTimeZone.toLocal8Bit().constData()); + tzset(); +} + void tst_QDateTime::toString_strformat_data() { QTest::addColumn("dt"); -- cgit v1.2.3