Make Qt::RFC2822Date's doc match up with its implementation

The qdatetime implementation's rfcDateImpl() uses regexes which did
not match its comments; nor did either the regexes or the comments
match what was documented. A review of relevant RFCs suggests we
should revise this in future, probably at Qt 6.

The documentation also only addressed the formats recognized when
parsing a date-time, without indicating how they are serialised or how
dates and times are handled separately.

Added a note to the tests for the read-only formats, to remind the
reader that the RFCs merely recommend recognising these - be
permissive in what you expect and strict in what you deliver.

Change-Id: I0f0bec752e7a50bde98cceceb7e0d11be15c6a6f
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Edward Welbourne 2019-11-13 18:42:00 +01:00
parent 8a60244da8
commit 6566157df3
5 changed files with 17 additions and 9 deletions

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@ -724,9 +724,17 @@
\value LocalDate \e{This enum value is deprecated.} Use Qt::SystemLocaleShortDate
instead (or Qt::SystemLocaleLongDate if you want long dates).
\value RFC2822Date \l{RFC 2822}, \l{RFC 850} and \l{RFC 1036} format: either
\c{[ddd,] dd MMM yyyy hh:mm[:ss] +/-TZ} or \c{ddd MMM dd yyyy hh:mm[:ss] +/-TZ}
for combined dates and times.
\value RFC2822Date \l{RFC 2822}, \l{RFC 850} and \l{RFC 1036} format:
either \c{[ddd,] dd MMM yyyy [hh:mm[:ss]][ ±tzoff]}
or \c{ddd MMM dd[ hh:mm:ss] yyyy[ ±tzoff]} are recognized for combined dates
and times, where \c{tzoff} is a timezone offset in \c{hhmm} format. For
dates and times separately, the same formats are matched and the unwanted
parts are ignored. In particular, note that a time is not recognized without
an accompanying date. When converting dates to string form,
format \c{dd MMM yyyy} is used, for times the format is \c{hh:mm:ss}. For
combined date and time, these are combined
as \c{dd MMM yyyy hh:mm:ss ±tzoff} (omitting the optional leading day of the
week from the first format recognized).
\note For \c ISODate formats, each \c Y, \c M and \c D represents a single digit
of the year, month and day used to specify the date. Each \c H, \c M and \c S

View File

@ -164,7 +164,7 @@ static ParsedRfcDateTime rfcDateImpl(const QString &s)
{
ParsedRfcDateTime result;
// Matches "Wdy, dd Mon yyyy HH:mm:ss ±hhmm" (Wdy, being optional)
// Matches "[ddd,] dd MMM yyyy[ hh:mm[:ss]] [±hhmm]" - correct RFC 822, 2822, 5322 format
QRegExp rex(QStringLiteral("^(?:[A-Z][a-z]+,)?[ \\t]*(\\d{1,2})[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d)(?::(\\d\\d))?)?[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?"));
if (s.indexOf(rex) == 0) {
const QStringList cap = rex.capturedTexts();
@ -176,7 +176,7 @@ static ParsedRfcDateTime rfcDateImpl(const QString &s)
const int minOffset = cap[9].toInt();
result.utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60));
} else {
// Matches "Wdy Mon dd HH:mm:ss yyyy"
// Matches "ddd MMM dd[ hh:mm:ss] yyyy [±hhmm]" - permissive RFC 850, 1036 (read only)
QRegExp rex(QStringLiteral("^[A-Z][a-z]+[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d):(\\d\\d))?[ \\t]+(\\d\\d\\d\\d)[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?"));
if (s.indexOf(rex) == 0) {
const QStringList cap = rex.capturedTexts();

View File

@ -1165,7 +1165,7 @@ void tst_QDate::fromStringDateFormat_data()
QTest::newRow("RFC 2822 invalid character 2 at front") << QString::fromLatin1("!!01 Jan 2012 08:00:00 +0000")
<< Qt::RFC2822Date << QDate();
// Test Qt::RFC2822Date format (RFC 850 and 1036).
// Test Qt::RFC2822Date format (RFC 850 and 1036, permissive).
QTest::newRow("RFC 850 and 1036") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100")
<< Qt::RFC2822Date << QDate(1987, 2, 13);
// No timezone

View File

@ -2351,7 +2351,7 @@ void tst_QDateTime::fromStringDateFormat_data()
QTest::newRow("RFC 2822 invalid character 2 at front") << QString::fromLatin1("!!01 Jan 2012 08:00:00 +0000")
<< Qt::RFC2822Date << invalidDateTime();
// Test Qt::RFC2822Date format (RFC 850 and 1036).
// Test Qt::RFC2822Date format (RFC 850 and 1036, permissive).
QTest::newRow("RFC 850 and 1036 +0100") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100")
<< Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC);
QTest::newRow("RFC 850 and 1036 -0100") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 -0100")

View File

@ -648,7 +648,7 @@ void tst_QTime::fromStringDateFormat_data()
QTest::newRow("RFC 2822 invalid character 2 at front") << QString::fromLatin1("!!01 Jan 2012 08:00:00 +0000")
<< Qt::RFC2822Date << invalidTime();
// Test Qt::RFC2822Date format (RFC 850 and 1036).
// Test Qt::RFC2822Date format (RFC 850 and 1036, permissive).
QTest::newRow("RFC 850 and 1036") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100")
<< Qt::RFC2822Date << QTime(13, 24, 51);
// No timezone