Drop parsing of antique TextDate format

Apparently we used to have (back in 2007, only on Windows,
incompatibly with what we were then using on Unix) a TextDate format
(only for QDateTime, QDate used what it still uses) that put the
day-of-month number, with a dot after it, before the month's short
name. We have retained parsing of this format, on all platforms, ever
since.

It no longer matches the format we now use (since 5.2, in 2013, commit
61b56a89a1cf8a388ff925492700e5eef019c3aa, which harmonised the format
with Unix and QDate); now seems like a good time to stop complicating
our parser for its sake.

[ChangeLog][QtCore][QDateTime] The parsing of Qt::TextDate in
QDateTime::fromString() no longer supports the old TextDate format
used (only) on Windows by Qt < 5.2 ("ddd d. MMM yyyy" with an
"HH:mm:ss" time either appended or inserted before "yyyy").

Change-Id: I73a798ab78f187543e415119cc4a11f1cfd73820
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Edward Welbourne 2021-02-11 17:11:29 +01:00
parent 517578e071
commit c462793d67
2 changed files with 50 additions and 70 deletions

View File

@ -1480,6 +1480,7 @@ QDate QDate::fromString(QStringView string, Qt::DateFormat format)
return rfcDateImpl(string).date;
default:
case Qt::TextDate: {
// Documented as "ddd MMM d yyyy"
auto parts = string.split(u' ', Qt::SkipEmptyParts);
if (parts.count() != 4)
@ -4883,11 +4884,11 @@ QDateTime QDateTime::fromString(QStringView string, Qt::DateFormat format)
case Qt::TextDate: {
QList<QStringView> parts = string.split(u' ', Qt::SkipEmptyParts);
if ((parts.count() < 5) || (parts.count() > 6))
// Documented as "ddd MMM d HH:mm:ss yyyy" with optional offset-suffix;
// and allow time either before or after year.
if (parts.count() < 5 || parts.count() > 6)
return QDateTime();
// Accept "Sun Dec 1 13:02:00 1974" and "Sun 1. Dec 13:02:00 1974"
// Year and time can be in either order.
// Guess which by looking for ':' in the time
int yearPart = 3;
@ -4899,31 +4900,11 @@ QDateTime QDateTime::fromString(QStringView string, Qt::DateFormat format)
else
return QDateTime();
int month = 0;
int day = 0;
bool ok = false;
int year = parts.at(yearPart).toInt(&ok);
if (!ok || year == 0)
return QDateTime();
// Next try month then day
month = fromShortMonthName(parts.at(1));
if (month)
day = parts.at(2).toInt(&ok);
// If failed, try day then month
if (!ok || !month || !day) {
month = fromShortMonthName(parts.at(2));
if (month) {
QStringView dayPart = parts.at(1);
if (dayPart.endsWith(u'.'))
day = dayPart.chopped(1).toInt(&ok);
}
}
// If both failed, give up
if (!ok || !month || !day)
int day = parts.at(2).toInt(&ok);
int year = ok ? parts.at(yearPart).toInt(&ok) : 0;
int month = fromShortMonthName(parts.at(1));
if (!ok || year == 0 || day == 0 || month < 1)
return QDateTime();
const QDate date(year, month, day);

View File

@ -2222,17 +2222,17 @@ void tst_QDateTime::fromStringDateFormat_data()
<< Qt::TextDate << QDateTime(QDate(12345, 6, 17), QTime(8, 0, 10, 0), Qt::LocalTime);
QTest::newRow("text date Year -4712") << QString::fromLatin1("Tue Jan 1 00:01:02 -4712")
<< Qt::TextDate << QDateTime(QDate(-4712, 1, 1), QTime(0, 1, 2, 0), Qt::LocalTime);
QTest::newRow("text data0") << QString::fromLatin1("Thu Jan 1 00:00:00 1970")
<< Qt::TextDate << QDateTime(QDate(1970, 1, 1), QTime(0, 0), Qt::LocalTime);
QTest::newRow("text epoch")
<< QString::fromLatin1("Thu Jan 1 00:00:00 1970") << Qt::TextDate
<< QDateTime(QDate(1970, 1, 1), QTime(0, 0), Qt::LocalTime);
QTest::newRow("text data1") << QString::fromLatin1("Thu Jan 2 12:34 1970")
<< Qt::TextDate << QDateTime(QDate(1970, 1, 2), QTime(12, 34, 0), Qt::LocalTime);
QTest::newRow("text data2") << QString::fromLatin1("Thu Jan 1 00 1970")
<< Qt::TextDate << QDateTime();
QTest::newRow("text data3") << QString::fromLatin1("Thu Jan 1 00:00:00:00 1970")
<< Qt::TextDate << QDateTime();
QTest::newRow("text data4") << QString::fromLatin1("Thu 1. Jan 00:00:00 1970")
<< Qt::TextDate << QDateTime(QDate(1970, 1, 1), QTime(0, 0), Qt::LocalTime);
QTest::newRow("text data5") << QString::fromLatin1(" Thu Jan 1 00:00:00 1970 ")
QTest::newRow("text epoch terse")
<< QString::fromLatin1("Thu Jan 1 00 1970") << Qt::TextDate << QDateTime();
QTest::newRow("text epoch stray :00")
<< QString::fromLatin1("Thu Jan 1 00:00:00:00 1970") << Qt::TextDate << QDateTime();
QTest::newRow("text epoch spaced")
<< QString::fromLatin1(" Thu Jan 1 00:00:00 1970 ")
<< Qt::TextDate << QDateTime(QDate(1970, 1, 1), QTime(0, 0), Qt::LocalTime);
QTest::newRow("text data6") << QString::fromLatin1("Thu Jan 1 00:00:00")
<< Qt::TextDate << QDateTime();
@ -2268,47 +2268,46 @@ void tst_QDateTime::fromStringDateFormat_data()
<< Qt::TextDate << QDateTime();
QTest::newRow("text invalid date") << QString::fromLatin1("Thu Jan 32 1970 00:12:34")
<< Qt::TextDate << QDateTime();
QTest::newRow("text invalid day #1") << QString::fromLatin1("Thu Jan XX 1970 00:12:34")
<< Qt::TextDate << QDateTime();
QTest::newRow("text invalid day #2") << QString::fromLatin1("Thu X. Jan 00:00:00 1970")
<< Qt::TextDate << QDateTime();
QTest::newRow("text invalid day #3") << QString::fromLatin1("Thu 1 Jan 00:00:00 1970")
<< Qt::TextDate << QDateTime();
QTest::newRow("text invalid year #1") << QString::fromLatin1("Thu 1. Jan 00:00:00 19X0")
<< Qt::TextDate << QDateTime();
QTest::newRow("text invalid year #2") << QString::fromLatin1("Thu 1. Jan 19X0 00:00:00")
<< Qt::TextDate << QDateTime();
QTest::newRow("text invalid hour") << QString::fromLatin1("Thu 1. Jan 1970 0X:00:00")
<< Qt::TextDate << QDateTime();
QTest::newRow("text invalid minute") << QString::fromLatin1("Thu 1. Jan 1970 00:0X:00")
<< Qt::TextDate << QDateTime();
QTest::newRow("text invalid second") << QString::fromLatin1("Thu 1. Jan 1970 00:00:0X")
<< Qt::TextDate << QDateTime();
QTest::newRow("text bad UTC specifier #1") << QString::fromLatin1("Thu 1. Jan 1970 00:00:00 DMT")
<< Qt::TextDate << QDateTime();
QTest::newRow("text bad UTC specifier #2") << QString::fromLatin1("Thu 1. Jan 1970 00:00:00 UTCx0200")
<< Qt::TextDate << QDateTime();
QTest::newRow("text bad UTC hour") << QString::fromLatin1("Thu 1. Jan 1970 00:00:00 UTC+0X00")
<< Qt::TextDate << QDateTime();
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")
QTest::newRow("text pre-5.2 MS-Win format") // Support dropped in 6.2
<< QString::fromLatin1("Thu 1. Jan 00:00:00 1970") << Qt::TextDate << QDateTime();
QTest::newRow("text invalid day")
<< QString::fromLatin1("Thu Jan XX 1970 00:12:34") << Qt::TextDate << QDateTime();
QTest::newRow("text misplaced day")
<< QString::fromLatin1("Thu 1 Jan 00:00:00 1970") << Qt::TextDate << QDateTime();
QTest::newRow("text invalid year end")
<< QString::fromLatin1("Thu Jan 1 00:00:00 19X0") << Qt::TextDate << QDateTime();
QTest::newRow("text invalid year early")
<< QString::fromLatin1("Thu Jan 1 19X0 00:00:00") << Qt::TextDate << QDateTime();
QTest::newRow("text invalid hour")
<< QString::fromLatin1("Thu Jan 1 1970 0X:00:00") << Qt::TextDate << QDateTime();
QTest::newRow("text invalid minute")
<< QString::fromLatin1("Thu Jan 1 1970 00:0X:00") << Qt::TextDate << QDateTime();
QTest::newRow("text invalid second")
<< QString::fromLatin1("Thu Jan 1 1970 00:00:0X") << Qt::TextDate << QDateTime();
QTest::newRow("text non-UTC offset")
<< QString::fromLatin1("Thu Jan 1 1970 00:00:00 DMT") << Qt::TextDate << QDateTime();
QTest::newRow("text bad UTC offset")
<< QString::fromLatin1("Thu Jan 1 1970 00:00:00 UTCx0200") << Qt::TextDate << QDateTime();
QTest::newRow("text bad UTC hour")
<< QString::fromLatin1("Thu Jan 1 1970 00:00:00 UTC+0X00") << Qt::TextDate << QDateTime();
QTest::newRow("text bad UTC minute")
<< QString::fromLatin1("Thu Jan 1 1970 00:00:00 UTC+000X") << Qt::TextDate << QDateTime();
QTest::newRow("text second fraction")
<< QString::fromLatin1("Mon May 6 2013 01:02:03.456")
<< Qt::TextDate << QDateTime(QDate(2013, 5, 6), QTime(1, 2, 3, 456));
QTest::newRow("text max milli")
<< QString::fromLatin1("Mon 6. May 2013 01:02:03.999499999")
<< QString::fromLatin1("Mon May 6 2013 01:02:03.999499999")
<< Qt::TextDate << QDateTime(QDate(2013, 5, 6), QTime(1, 2, 3, 999));
QTest::newRow("text milli wrap")
<< QString::fromLatin1("Mon 6. May 2013 01:02:03.9995")
<< QString::fromLatin1("Mon May 6 2013 01:02:03.9995")
<< Qt::TextDate << QDateTime(QDate(2013, 5, 6), QTime(1, 2, 4));
QTest::newRow("text last milli") // Special case, don't round up to invalid:
<< QString::fromLatin1("Mon 6. May 2013 23:59:59.9999999999")
<< QString::fromLatin1("Mon May 6 2013 23:59:59.9999999999")
<< Qt::TextDate << QDateTime(QDate(2013, 5, 6), QTime(23, 59, 59, 999));
const QDateTime ref(QDate(1974, 12, 1), QTime(13, 2));
QTest::newRow("day:,:month")
<< QStringLiteral("Sun 1. Dec 13:02:00 1974") << Qt::TextDate << ref;
QTest::newRow("month:day")
<< QStringLiteral("Sun Dec 1 13:02:00 1974") << Qt::TextDate << ref;
QTest::newRow("text Sunday lunch")
<< QStringLiteral("Sun Dec 1 13:02:00 1974") << Qt::TextDate
<< QDateTime(QDate(1974, 12, 1), QTime(13, 2));
// Test Qt::ISODate format.
QTest::newRow("trailing space") // QTBUG-80445