Prepare TextDate to use UTC-offset rather than GMT-offset zone suffixes
There are GMT-offset zones whose convention for the sign of the offset is the reverse of what we are (still) using, which is the usual convention for UTC-offset zone: for example, the Olson Database's Etc/GMT+3 has offset -3 hours in the UTC-based system we use, so we give it suffix GMT-0300. The UTC-based suffix is also what we use as the abbreviation for OffsetFromUTC() in toString(). For now this only adds support for parsing a planned future form: the old form using GMT is retained, to give client code some chance to prepare for a backwards-compatible transition. Although the GMT prefix is matched case-insensitively, only match UTC if fully upper-case; there is no meaningful precedent for case-insensitive usage here. [ChangeLog][QtCore][QDateTime] The Qt::TextDate format now recognizes UTC-based offset suffixes in addition to suffixes based on the deprecated alias GMT. This prepares for toString() to use such UTC-based suffixes for time-zones (fromString() cannot parse the present abbreviation suffix). A future release of Qt shall use UTC-based suffixes in place of the present GMT-based suffixes (which conflict with GMT-based IANA zone names) for Qt::LocalTime and Qt::OffsetFromUTC time-specs. Client code is encouraged to use and recognize UTC-based zone suffixes in preparation for that transition, unless compatibility with versions before 6.2 is required. Change-Id: I5a42a488f1232a30f4b427b7954759283423b9b3 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
73fbf8bd30
commit
3cf84287e7
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Copyright (C) 2020 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
@ -669,9 +669,15 @@
|
||||
names will be short names in English (C locale). This effectively uses, for
|
||||
a date, format \c{ddd MMM d yyyy}, for a time \c{HH:mm:ss} and combines
|
||||
these as \c{ddd MMM d HH:mm:ss yyyy} for a date-time, with an optional
|
||||
suffix indicating time-zone or offset from UTC, where relevant. A fractional
|
||||
part is also recognized on the seconds of a time part, as \c{HH:mm:ss.zzz},
|
||||
when reading from a string.
|
||||
zone-offset suffix, where relevant. When reading from a string, a
|
||||
fractional part is also recognized on the seconds of a time part, as
|
||||
\c{HH:mm:ss.zzz}, and some minor variants on the format may be recognized,
|
||||
for compatibility with earlier versions of Qt and with changes to the format
|
||||
planned for the future. In particular, the zone-offset suffix presently uses
|
||||
\c{GMT[±tzoff]} with a \c{tzoff} in \c{HH[[:]mm]} format (two-digit hour and
|
||||
optional two-digit minutes, with optional colon separator); this shall
|
||||
change to use \c{UTC} in place of \c{GMT} in a future release of Qt, so the
|
||||
planned \c{UTC} format is recognized.
|
||||
|
||||
\value ISODateWithMs \l{ISO 8601} extended format: uses \c{yyyy-MM-dd} for
|
||||
dates, \c{HH:mm:ss.zzz} for times or \c{yyyy-MM-ddTHH:mm:ss.zzz}
|
||||
@ -721,6 +727,11 @@
|
||||
of the format. The plus-or-minus character \c{'±'} here stands for either
|
||||
sign character, \c{'-'} for minus or \c{'+'} for plus.
|
||||
|
||||
\note Zone offsets are measured positive to the east of Greenwich, negative
|
||||
to the west, as is usual for UTC-based offset notations (conflicting with
|
||||
some GMT-based zones-names, such as \c{Etc/GMT+3}, which use the opposite
|
||||
convention).
|
||||
|
||||
\sa QDate::toString(), QTime::toString(), QDateTime::toString(),
|
||||
QDate::fromString(), QTime::fromString(), QDateTime::fromString()
|
||||
*/
|
||||
|
@ -4033,7 +4033,11 @@ QString QDateTime::toString(Qt::DateFormat format) const
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
#if 0 // ### Qt 7 GMT: use UTC instead, see qnamespace.qdoc documentation
|
||||
buf += QLatin1String(" UTC");
|
||||
#else
|
||||
buf += QLatin1String(" GMT");
|
||||
#endif
|
||||
if (getSpec(d) == Qt::OffsetFromUTC)
|
||||
buf += toOffsetString(Qt::TextDate, offsetFromUtc());
|
||||
}
|
||||
@ -4933,17 +4937,17 @@ QDateTime QDateTime::fromString(QStringView string, Qt::DateFormat format)
|
||||
return QDateTime(date, time, Qt::LocalTime);
|
||||
|
||||
QStringView tz = parts.at(5);
|
||||
if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive))
|
||||
return QDateTime();
|
||||
tz = tz.sliced(3);
|
||||
if (!tz.isEmpty()) {
|
||||
if (tz.startsWith(QLatin1String("UTC"))
|
||||
// GMT has long been deprecated as an alias for UTC.
|
||||
|| tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive)) {
|
||||
tz = tz.sliced(3);
|
||||
if (tz.isEmpty())
|
||||
return QDateTime(date, time, Qt::UTC);
|
||||
|
||||
int offset = fromOffsetString(tz, &ok);
|
||||
if (!ok)
|
||||
return QDateTime();
|
||||
return QDateTime(date, time, Qt::OffsetFromUTC, offset);
|
||||
} else {
|
||||
return QDateTime(date, time, Qt::UTC);
|
||||
return ok ? QDateTime(date, time, Qt::OffsetFromUTC, offset) : QDateTime();
|
||||
}
|
||||
return QDateTime();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -895,6 +895,7 @@ void tst_QDateTime::toString_textDate_data()
|
||||
const QString wednesdayJanuary = QLocale::c().dayName(3, QLocale::ShortFormat)
|
||||
+ ' ' + QLocale::c().monthName(1, QLocale::ShortFormat);
|
||||
|
||||
// ### Qt 7 GMT: change to UTC - see matching QDateTime::fromString() comment
|
||||
QTest::newRow("localtime") << QDateTime(QDate(2013, 1, 2), QTime(1, 2, 3), Qt::LocalTime)
|
||||
<< wednesdayJanuary + QString(" 2 01:02:03 2013");
|
||||
QTest::newRow("utc") << QDateTime(QDate(2013, 1, 2), QTime(1, 2, 3), Qt::UTC)
|
||||
@ -929,6 +930,7 @@ void tst_QDateTime::toString_textDate()
|
||||
|
||||
void tst_QDateTime::toString_textDate_extra()
|
||||
{
|
||||
// ### Qt 7 GMT: change to UTC - see matching QDateTime::fromString() comment
|
||||
auto endsWithGmt = [](const QDateTime &dt) {
|
||||
return dt.toString().endsWith(QLatin1String("GMT"));
|
||||
};
|
||||
@ -2247,21 +2249,31 @@ void tst_QDateTime::fromStringDateFormat_data()
|
||||
<< Qt::TextDate << QDateTime();
|
||||
QTest::newRow("text data7") << QString::fromLatin1("Thu Jan 1 1970 00:00:00")
|
||||
<< Qt::TextDate << QDateTime(QDate(1970, 1, 1), QTime(0, 0), Qt::LocalTime);
|
||||
QTest::newRow("text data8") << QString::fromLatin1("Thu Jan 1 00:12:34 1970 GMT+foo")
|
||||
QTest::newRow("text bad offset") << QString::fromLatin1("Thu Jan 1 00:12:34 1970 UTC+foo")
|
||||
<< Qt::TextDate << QDateTime();
|
||||
QTest::newRow("text data9") << QString::fromLatin1("Thu Jan 1 00:12:34 1970 GMT")
|
||||
QTest::newRow("text UTC early") << QString::fromLatin1("Thu Jan 1 00:12:34 1970 UTC")
|
||||
<< Qt::TextDate << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
|
||||
QTest::newRow("text data10") << QString::fromLatin1("Thu Jan 1 00:12:34 1970 GMT-0300")
|
||||
QTest::newRow("text UTC-3 early") << QString::fromLatin1("Thu Jan 1 00:12:34 1970 UTC-0300")
|
||||
<< Qt::TextDate << QDateTime(QDate(1970, 1, 1), QTime(3, 12, 34), Qt::UTC);
|
||||
QTest::newRow("text data11") << QString::fromLatin1("Thu Jan 1 00:12:34 1970 GMT+0300")
|
||||
QTest::newRow("text UTC+3 early") << QString::fromLatin1("Thu Jan 1 00:12:34 1970 UTC+0300")
|
||||
<< Qt::TextDate << QDateTime(QDate(1969, 12, 31), QTime(21, 12, 34), Qt::UTC);
|
||||
QTest::newRow("text data12") << QString::fromLatin1("Thu Jan 1 00:12:34 1970 gmt")
|
||||
<< Qt::TextDate << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
|
||||
QTest::newRow("text data13") << QString::fromLatin1("Thu Jan 1 1970 00:12:34 GMT+0100")
|
||||
QTest::newRow("text UTC+1 early") << QString::fromLatin1("Thu Jan 1 1970 00:12:34 UTC+0100")
|
||||
<< Qt::TextDate << QDateTime(QDate(1969, 12, 31), QTime(23, 12, 34), Qt::UTC);
|
||||
// We produce use GMT as prefix, so need to parse it:
|
||||
QTest::newRow("text GMT early")
|
||||
<< QString::fromLatin1("Thu Jan 1 00:12:34 1970 GMT") << Qt::TextDate
|
||||
<< QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
|
||||
QTest::newRow("text GMT+3 early")
|
||||
<< QString::fromLatin1("Thu Jan 1 00:12:34 1970 GMT+0300") << Qt::TextDate
|
||||
<< QDateTime(QDate(1969, 12, 31), QTime(21, 12, 34), Qt::UTC);
|
||||
// ... and we match (only) it case-insensitively:
|
||||
QTest::newRow("text gmt early")
|
||||
<< QString::fromLatin1("Thu Jan 1 00:12:34 1970 gmt") << Qt::TextDate
|
||||
<< QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
|
||||
|
||||
QTest::newRow("text empty") << QString::fromLatin1("")
|
||||
<< Qt::TextDate << QDateTime();
|
||||
QTest::newRow("text too many parts") << QString::fromLatin1("Thu Jan 1 00:12:34 1970 gmt +0100")
|
||||
QTest::newRow("text too many parts") << QString::fromLatin1("Thu Jan 1 00:12:34 1970 UTC +0100")
|
||||
<< Qt::TextDate << QDateTime();
|
||||
QTest::newRow("text invalid month name") << QString::fromLatin1("Thu Jaz 1 1970 00:12:34")
|
||||
<< Qt::TextDate << QDateTime();
|
||||
@ -2283,13 +2295,13 @@ void tst_QDateTime::fromStringDateFormat_data()
|
||||
<< Qt::TextDate << QDateTime();
|
||||
QTest::newRow("text invalid second") << QString::fromLatin1("Thu 1. Jan 1970 00:00:0X")
|
||||
<< Qt::TextDate << QDateTime();
|
||||
QTest::newRow("text invalid gmt specifier #1") << QString::fromLatin1("Thu 1. Jan 1970 00:00:00 DMT")
|
||||
QTest::newRow("text bad UTC specifier #1") << QString::fromLatin1("Thu 1. Jan 1970 00:00:00 DMT")
|
||||
<< Qt::TextDate << QDateTime();
|
||||
QTest::newRow("text invalid gmt specifier #2") << QString::fromLatin1("Thu 1. Jan 1970 00:00:00 GMTx0200")
|
||||
QTest::newRow("text bad UTC specifier #2") << QString::fromLatin1("Thu 1. Jan 1970 00:00:00 UTCx0200")
|
||||
<< Qt::TextDate << QDateTime();
|
||||
QTest::newRow("text invalid gmt hour") << QString::fromLatin1("Thu 1. Jan 1970 00:00:00 GMT+0X00")
|
||||
QTest::newRow("text bad UTC hour") << QString::fromLatin1("Thu 1. Jan 1970 00:00:00 UTC+0X00")
|
||||
<< Qt::TextDate << QDateTime();
|
||||
QTest::newRow("text invalid gmt minute") << QString::fromLatin1("Thu 1. Jan 1970 00:00:00 GMT+000X")
|
||||
QTest::newRow("text bad UTC minute") << QString::fromLatin1("Thu 1. Jan 1970 00:00:00 UTC+000X")
|
||||
<< Qt::TextDate << QDateTime();
|
||||
QTest::newRow("text second fraction") << QString::fromLatin1("Mon 6. May 2013 01:02:03.456")
|
||||
<< Qt::TextDate << QDateTime(QDate(2013, 5, 6), QTime(1, 2, 3, 456));
|
||||
|
Loading…
Reference in New Issue
Block a user