Skip to content

Commit

Permalink
Fix QDateTime::toString(Qt::ISODate)'s handling of Qt::TimeZone
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
ediosyncratic committed Dec 14, 2016
1 parent 9d8db91 commit 7c33c64
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
16 changes: 14 additions & 2 deletions src/corelib/tools/qdatetime.cpp
Expand Up @@ -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)
{
Expand All @@ -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

Expand Down Expand Up @@ -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:
Expand Down
3 changes: 3 additions & 0 deletions src/corelib/tools/qdatetime_p.h
Expand Up @@ -136,6 +136,9 @@ class QDateTimePrivate
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(); }
Expand Down
23 changes: 23 additions & 0 deletions tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
Expand Up @@ -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();
Expand Down Expand Up @@ -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");
Expand Down

0 comments on commit 7c33c64

Please sign in to comment.