From 285596ee199ae1767fc48a0d0c2d12b178c0234d Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 9 Nov 2017 21:13:43 +0100 Subject: Special-case parsing of Zulu time-zone in date-times When parsing a date-time's zone, a stray Z denotes UTC (a.k.a. Zulu time), despite not being a valid name for the zone. Clients parsing such date strings had to treat the Z as a literal, rather than a zone-ID, but then they got back a LocalTime instead of the UTC the string actually described. So teach QTimeZoneParser to handle this special case and adapt an existing test (that used a time ending in Z, but had to treat it as a local time) to check this works. [ChangeLog][QtCore][QDateTime] When parsing a time-zone, "Z" is now recognized as an alias for UTC. Change-Id: Ib6aa2d8ea2dc6b2da526b39aec74dbc007f90fd8 Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetimeparser.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/corelib/tools/qdatetimeparser.cpp') diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index dd277f7753..4b3777407c 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -1155,7 +1155,8 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, // Synchronize with what findTimeZone() found: QStringRef zoneName = input->midRef(pos, sect.used); Q_ASSERT(!zoneName.isEmpty()); // sect.used > 0 - const QByteArray latinZone(zoneName.toLatin1()); + const QByteArray latinZone(zoneName == QLatin1String("Z") + ? QByteArray("UTC") : zoneName.toLatin1()); timeZone = QTimeZone(latinZone); tspec = timeZone.isValid() ? (QTimeZone::isTimeZoneIdAvailable(latinZone) @@ -1595,6 +1596,10 @@ QDateTimeParser::findTimeZone(QStringRef str, const QDateTime &when, while (index > 0) { str.truncate(index); + if (str == QLatin1String("Z")) { + offset = 0; // "Zulu" time - a.k.a. UTC + break; + } QTimeZone zone(str.toLatin1()); if (zone.isValid()) { offset = zone.offsetFromUtc(when); -- cgit v1.2.3 From 37c9d6deca9e7f0812fc38cc9729d58cb2e9d7ed Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 11 Sep 2017 18:14:51 +0200 Subject: Condition QDateTimeParser's time-zone parsing on QT_CONFIG(timezone) It was missing some #if-ery it needed. Change-Id: Ibc12f4a9ee35acb64a39a1c7a15d2934b5710dc0 Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetimeparser.cpp | 41 ++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 10 deletions(-) (limited to 'src/corelib/tools/qdatetimeparser.cpp') diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index dd277f7753..6860cd6ef0 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -195,9 +195,11 @@ bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const return false; // Preserve zone: - v = (tspec == Qt::TimeZone - ? QDateTime(newDate, newTime, v.timeZone()) - : QDateTime(newDate, newTime, tspec, offset)); + v = +#if QT_CONFIG(timezone) + tspec == Qt::TimeZone ? QDateTime(newDate, newTime, v.timeZone()) : +#endif + QDateTime(newDate, newTime, tspec, offset); return true; } @@ -213,7 +215,9 @@ int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const { const SectionNode &sn = sectionNode(s); switch (sn.type) { +#if QT_CONFIG(timezone) case TimeZoneSection: return QTimeZone::MaxUtcOffsetSecs; +#endif case Hour24Section: case Hour12Section: return 23; // this is special-cased in // parseSection. We want it to be @@ -248,7 +252,9 @@ int QDateTimeParser::absoluteMin(int s) const { const SectionNode &sn = sectionNode(s); switch (sn.type) { +#if QT_CONFIG(timezone) case TimeZoneSection: return QTimeZone::MinUtcOffsetSecs; +#endif case Hour24Section: case Hour12Section: case MinuteSection: @@ -766,9 +772,11 @@ QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionIndex, text->replace(offset, used, sectiontext.constData(), used); break; } case TimeZoneSection: +#if QT_CONFIG(timezone) result = findTimeZone(sectionTextRef, currentValue, absoluteMax(sectionIndex), absoluteMin(sectionIndex)); +#endif break; case MonthSection: case DayOfWeekSectionShort: @@ -1090,17 +1098,21 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, int dayofweek = defaultDate.dayOfWeek(); Qt::TimeSpec tspec = defaultValue.timeSpec(); int zoneOffset = 0; // In seconds; local - UTC +#if QT_CONFIG(timezone) QTimeZone timeZone; +#endif switch (tspec) { case Qt::OffsetFromUTC: // timeZone is ignored zoneOffset = defaultValue.offsetFromUtc(); break; +#if QT_CONFIG(timezone) case Qt::TimeZone: timeZone = defaultValue.timeZone(); if (timeZone.isValid()) zoneOffset = timeZone.offsetFromUtc(defaultValue); // else: is there anything we can do about this ? break; +#endif default: // zoneOffset and timeZone are ignored break; } @@ -1125,9 +1137,11 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, { const QDate date = actualDate(isSet, year, year2digits, month, day, dayofweek); const QTime time = actualTime(isSet, hour, hour12, ampm, minute, second, msec); - sect = parseSection(tspec == Qt::TimeZone - ? QDateTime(date, time, timeZone) - : QDateTime(date, time, tspec, zoneOffset), + sect = parseSection( +#if QT_CONFIG(timezone) + tspec == Qt::TimeZone ? QDateTime(date, time, timeZone) : +#endif + QDateTime(date, time, tspec, zoneOffset), index, pos, input); } @@ -1152,7 +1166,7 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, case TimeZoneSection: current = &zoneOffset; if (sect.used > 0) { - // Synchronize with what findTimeZone() found: +#if QT_CONFIG(timezone) // Synchronize with what findTimeZone() found: QStringRef zoneName = input->midRef(pos, sect.used); Q_ASSERT(!zoneName.isEmpty()); // sect.used > 0 const QByteArray latinZone(zoneName.toLatin1()); @@ -1162,6 +1176,9 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, ? Qt::TimeZone : Qt::OffsetFromUTC) : (Q_ASSERT(startsWithLocalTimeZone(zoneName)), Qt::LocalTime); +#else + tspec = Qt::LocalTime; +#endif } break; case Hour24Section: current = &hour; break; @@ -1319,9 +1336,11 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, const QDate date(year, month, day); const QTime time(hour, minute, second, msec); - return StateNode(tspec == Qt::TimeZone - ? QDateTime(date, time, timeZone) - : QDateTime(date, time, tspec, zoneOffset), + return StateNode( +#if QT_CONFIG(timezone) + tspec == Qt::TimeZone ? QDateTime(date, time, timeZone) : +#endif + QDateTime(date, time, tspec, zoneOffset), state, padding, conflicts); } @@ -1569,6 +1588,7 @@ QDateTimeParser::ParsedSection QDateTimeParser::findTimeZone(QStringRef str, const QDateTime &when, int maxVal, int minVal) const { +#if QT_CONFIG(timezone) int index = startsWithLocalTimeZone(str); int offset; @@ -1607,6 +1627,7 @@ QDateTimeParser::findTimeZone(QStringRef str, const QDateTime &when, if (index > 0 && maxVal >= offset && offset >= minVal) return ParsedSection(Acceptable, offset, index); +#endif // timezone return ParsedSection(); } -- cgit v1.2.3