Revert QDateTime serialisation to pre-Qt 5 behaviour.

In Qt 5, I managed to break the guarantee that a deserialised local
datetime is the same time of day (potentially different UTC time),
regardless of which timezone it was serialised in. This happened after
I fixed QTBUG-4057 with If650e7960dca7b6ab44b8233410a6369c41df73a,
which serialised datetimes as UTC.

This patch reverts QDateTime serialisation to pre-Qt 5 behaviour to
restore the guarantee and consequently re-opens QTBUG-4057.

Change-Id: Iea877f7ed886f530b928067789b53534e89fe8cb
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Mitch Curtis 2013-04-22 14:28:24 +02:00 committed by The Qt Project
parent 7e7d40eeb7
commit 83315ce8b2
6 changed files with 35 additions and 8 deletions

8
dist/changes-5.1.0 vendored
View File

@ -41,6 +41,14 @@ Third party components
* [QTBUG-8836] QAbstractItemView now allows manual deselect in
SingleSelection mode (with control modifier)
- QtCore
* The serialization behavior for QDateTime has reverted to pre-Qt 5,
due to the issue mentioned in section 4 here:
http://lists.qt-project.org/pipermail/development/2013-March/010559.html
This means that the QDataStream version will be 14 with Qt 5.1.
****************************************************************************
* Library *
****************************************************************************

View File

@ -539,7 +539,7 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_4_8 Same as Qt_4_6.
\value Qt_4_9 Same as Qt_4_6.
\value Qt_5_0 Version 13 (Qt 5.0)
\value Qt_5_1 Same as Qt_5_0.
\value Qt_5_1 Version 14 (Qt 5.1)
\sa setVersion(), version()
*/
@ -571,6 +571,7 @@ void QDataStream::setByteOrder(ByteOrder bo)
\table
\header \li Qt Version \li QDataStream Version
\row \li Qt 5.1 \li 14
\row \li Qt 5.0 \li 13
\row \li Qt 4.6 \li 12
\row \li Qt 4.5 \li 11

View File

@ -86,7 +86,7 @@ public:
Qt_4_8 = Qt_4_7,
Qt_4_9 = Qt_4_8,
Qt_5_0 = 13,
Qt_5_1 = Qt_5_0
Qt_5_1 = 14
#if QT_VERSION >= 0x050200
#error Add the datastream version for this Qt version
#endif

View File

@ -3691,8 +3691,11 @@ QDataStream &operator>>(QDataStream &in, QTime &time)
*/
QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
{
if (out.version() >= 13) {
if (out.version() == 13) {
if (dateTime.isValid()) {
// This approach is wrong and should not be used again; it breaks
// the guarantee that a deserialised local datetime is the same time
// of day, regardless of which timezone it was serialised in.
QDateTime asUTC = dateTime.toUTC();
out << asUTC.d->date << asUTC.d->time;
} else {
@ -3721,7 +3724,7 @@ QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
in >> dateTime.d->date >> dateTime.d->time;
if (in.version() >= 13) {
if (in.version() == 13) {
qint8 ts = 0;
in >> ts;
if (dateTime.isValid()) {

View File

@ -268,7 +268,8 @@ static int NColorRoles[] = {
QPalette::ToolTipText + 1, // Qt_4_5
QPalette::ToolTipText + 1, // Qt_4_6
QPalette::ToolTipText + 1, // Qt_5_0
0 // add the correct value for Qt_5_1 here later
QPalette::ToolTipText + 1, // Qt_5_1
0 // add the correct value for Qt_5_2 here later
};
// Testing get/set functions

View File

@ -1398,13 +1398,19 @@ void tst_QDateTime::operator_insert_extract()
{
QDataStream dataStream(&byteArray, QIODevice::WriteOnly);
dataStream.setVersion(dataStreamVersion);
if (dataStreamVersion >= QDataStream::Qt_5_0) {
if (dataStreamVersion == QDataStream::Qt_5_0) {
// Qt 5 serialises as UTC and converts back to the stored timeSpec when
// deserialising; we don't need to do it ourselves...
dataStream << dateTime << dateTime;
} else {
// ... but lower versions don't, so we have to here.
// ... but other versions don't, so we have to here.
dataStream << dateTimeAsUTC << dateTimeAsUTC;
// We'll also make sure that a deserialised local datetime is the same
// time of day (potentially different UTC time), regardless of which
// timezone it was serialised in. E.g.: Tue Aug 14 08:00:00 2012
// serialised in WST should be deserialised as Tue Aug 14 08:00:00 2012
// HST.
dataStream << dateTime;
}
}
@ -1420,7 +1426,7 @@ void tst_QDateTime::operator_insert_extract()
QDateTime deserialised;
dataStream >> deserialised;
if (dataStreamVersion >= QDataStream::Qt_5_0) {
if (dataStreamVersion == QDataStream::Qt_5_0) {
// Ensure local time is still correct. Again, Qt 5 handles the timeSpec
// conversion (in this case, UTC => LocalTime) for us when deserialising.
QCOMPARE(deserialised, expectedLocalTime);
@ -1453,6 +1459,14 @@ void tst_QDateTime::operator_insert_extract()
QCOMPARE(deserialised, expectedLocalTime);
// Sanity check UTC times.
QCOMPARE(deserialised.toUTC(), expectedLocalTime.toUTC());
if (dataStreamVersion != QDataStream::Qt_5_0) {
// Deserialised local datetime should be the same time of day,
// regardless of which timezone it was serialised in.
QDateTime localDeserialized;
dataStream >> localDeserialized;
QCOMPARE(localDeserialized, dateTime);
}
}
qputenv("TZ", previousTimeZone.toLocal8Bit().constData());