Fix QDateTime::toString(Qt::ISODate)'s handling of Qt::TimeZone

When the time is specified relative to a zone, the ISO date produced
lacked its offset suffix; all zones were treated as if they were local
time.  Handle zone as for an offset from UTC and ensure we do set the
date-time objects's offset from UTC when it's zone-based.

Change-Id: I7c9896bb8ec0a9d89df14a6e94b005174ab9e943
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Edward Welbourne 2016-11-21 18:17:07 +01:00
parent 9d8db91ada
commit 7c33c644d3
3 changed files with 40 additions and 2 deletions

View File

@ -2576,6 +2576,13 @@ static inline Qt::TimeSpec getSpec(const QDateTimeData &d)
return extractSpec(getStatus(d));
}
#if QT_CONFIG(timezone)
void QDateTimePrivate::setUtcOffsetByTZ(qint64 atMSecsSinceEpoch)
{
m_offsetFromUtc = m_timeZone.d->offsetFromUtc(atMSecsSinceEpoch);
}
#endif
// Refresh the LocalTime validity and offset
static void refreshDateTime(QDateTimeData &d)
{
@ -2591,10 +2598,12 @@ static void refreshDateTime(QDateTimeData &d)
#if QT_CONFIG(timezone)
// If not valid time zone then is invalid
if (spec == Qt::TimeZone) {
if (!d->m_timeZone.isValid())
if (!d->m_timeZone.isValid()) {
status &= ~QDateTimePrivate::ValidDateTime;
else
} else {
epochMSecs = QDateTimePrivate::zoneMSecsToEpochMSecs(msecs, d->m_timeZone, extractDaylightStatus(status), &testDate, &testTime);
d->setUtcOffsetByTZ(epochMSecs);
}
}
#endif // timezone
@ -3822,6 +3831,9 @@ QString QDateTime::toString(Qt::DateFormat format) const
buf += QLatin1Char('Z');
break;
case Qt::OffsetFromUTC:
#if QT_CONFIG(timezone)
case Qt::TimeZone:
#endif
buf += toOffsetString(Qt::ISODate, offsetFromUtc());
break;
default:

View File

@ -136,6 +136,9 @@ public:
static qint64 zoneMSecsToEpochMSecs(qint64 msecs, const QTimeZone &zone,
DaylightStatus hint = UnknownDaylightTime,
QDate *localDate = 0, QTime *localTime = 0);
// Inlined for its one caller in qdatetime.cpp
inline void setUtcOffsetByTZ(qint64 atMSecsSinceEpoch);
#endif // timezone
static inline qint64 minJd() { return QDate::minJd(); }

View File

@ -77,6 +77,7 @@ private slots:
void fromMSecsSinceEpoch();
void toString_isoDate_data();
void toString_isoDate();
void toString_isoDate_extra();
void toString_textDate_data();
void toString_textDate();
void toString_rfcDate_data();
@ -794,6 +795,28 @@ void tst_QDateTime::toString_isoDate()
QLocale::setDefault(oldLocale);
}
void tst_QDateTime::toString_isoDate_extra()
{
QDateTime dt = QDateTime::fromMSecsSinceEpoch(0, Qt::UTC);
QCOMPARE(dt.toString(Qt::ISODate), QLatin1String("1970-01-01T00:00:00Z"));
#if QT_CONFIG(timezone)
QTimeZone PST("America/Vancouver");
if (PST.isValid()) {
dt = QDateTime::fromMSecsSinceEpoch(0, PST);
QCOMPARE(dt.toString(Qt::ISODate), QLatin1String("1969-12-31T16:00:00-08:00"));
} else {
qDebug("Missed zone test: no America/Vancouver zone available");
}
QTimeZone CET("Europe/Berlin");
if (CET.isValid()) {
dt = QDateTime::fromMSecsSinceEpoch(0, CET);
QCOMPARE(dt.toString(Qt::ISODate), QLatin1String("1970-01-01T01:00:00+01:00"));
} else {
qDebug("Missed zone test: no Europe/Berlin zone available");
}
#endif // timezone
}
void tst_QDateTime::toString_textDate_data()
{
QTest::addColumn<QDateTime>("datetime");