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 <thiago.macieira@intel.com>
This commit is contained in:
parent
17c89d157a
commit
718a2251be
@ -3666,9 +3666,19 @@ QDataStream &operator>>(QDataStream &in, QTime &time)
|
||||
*/
|
||||
QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
|
||||
{
|
||||
out << dateTime.d->date << dateTime.d->time;
|
||||
if (out.version() >= 7)
|
||||
out << (qint8)dateTime.d->spec;
|
||||
if (out.version() >= 13) {
|
||||
if (dateTime.isValid()) {
|
||||
QDateTime asUTC = dateTime.toUTC();
|
||||
out << asUTC.d->date << asUTC.d->time;
|
||||
} else {
|
||||
out << dateTime.d->date << dateTime.d->time;
|
||||
}
|
||||
out << (qint8)dateTime.timeSpec();
|
||||
} else {
|
||||
out << dateTime.d->date << dateTime.d->time;
|
||||
if (out.version() >= 7)
|
||||
out << (qint8)dateTime.d->spec;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -3684,11 +3694,22 @@ QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
|
||||
{
|
||||
dateTime.detach();
|
||||
|
||||
qint8 ts = (qint8)QDateTimePrivate::LocalUnknown;
|
||||
in >> dateTime.d->date >> dateTime.d->time;
|
||||
if (in.version() >= 7)
|
||||
|
||||
if (in.version() >= 13) {
|
||||
qint8 ts = 0;
|
||||
in >> ts;
|
||||
dateTime.d->spec = (QDateTimePrivate::Spec)ts;
|
||||
if (dateTime.isValid()) {
|
||||
// We always store the datetime as UTC in 13 onwards.
|
||||
dateTime.d->spec = QDateTimePrivate::UTC;
|
||||
dateTime = dateTime.toTimeSpec(static_cast<Qt::TimeSpec>(ts));
|
||||
}
|
||||
} else {
|
||||
qint8 ts = (qint8)QDateTimePrivate::LocalUnknown;
|
||||
if (in.version() >= 7)
|
||||
in >> ts;
|
||||
dateTime.d->spec = (QDateTimePrivate::Spec)ts;
|
||||
}
|
||||
return in;
|
||||
}
|
||||
#endif // QT_NO_DATASTREAM
|
||||
|
@ -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<QDateTime>("dateTime");
|
||||
QTest::addColumn<QString>("serialiseAs");
|
||||
QTest::addColumn<QString>("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<Qt::TimeSpec>(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<QDateTime>("dt");
|
||||
|
Loading…
Reference in New Issue
Block a user