Add the RFC2822Date format

QDateTime can now be converted to strings compliant to RFC 2822.
Additionally, it supports RFC 850 and RFC 1036 during parsing.
By having them all together, all type of dates found in exchanged
messages on the internet (including USENET) get supported.

Change-Id: I771066c23f409d20b31b7d802f37852ea68ca2a0
Reviewed-by: David Faure <david.faure@kdab.com>
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@digia.com>
This commit is contained in:
Kevin Ottens 2013-07-13 11:01:34 +02:00 committed by The Qt Project
parent 828c034f1e
commit 288e50227d
7 changed files with 379 additions and 1 deletions

View File

@ -77,3 +77,18 @@
\externalpage http://www.rfc-editor.org/rfc/rfc3986.txt \externalpage http://www.rfc-editor.org/rfc/rfc3986.txt
\title RFC 3986 \title RFC 3986
*/ */
/*!
\externalpage http://www.rfc-editor.org/rfc/rfc2822.txt
\title RFC 2822
*/
/*!
\externalpage http://www.rfc-editor.org/rfc/rfc1036.txt
\title RFC 1036
*/
/*!
\externalpage http://www.rfc-editor.org/rfc/rfc850.txt
\title RFC 850
*/

View File

@ -1181,7 +1181,8 @@ public:
SystemLocaleShortDate, SystemLocaleShortDate,
SystemLocaleLongDate, SystemLocaleLongDate,
DefaultLocaleShortDate, DefaultLocaleShortDate,
DefaultLocaleLongDate DefaultLocaleLongDate,
RFC2822Date // RFC 2822 (+ 850 and 1036 during parsing)
}; };
enum TimeSpec { enum TimeSpec {

View File

@ -585,6 +585,10 @@
\value LocalDate \e{This enum value is deprecated.} Use Qt::SystemLocaleShortDate \value LocalDate \e{This enum value is deprecated.} Use Qt::SystemLocaleShortDate
instead (or Qt::SystemLocaleLongDate if you want long dates). 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.
\note For \c ISODate formats, each \c Y, \c M and \c D represents a single digit \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 of the year, month and day used to specify the date. Each \c H, \c M and \c S
represents a single digit of the hour, minute and second used to specify the time. represents a single digit of the hour, minute and second used to specify the time.

View File

@ -158,9 +158,19 @@ static const char monthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,
static const char * const qt_shortMonthNames[] = { static const char * const qt_shortMonthNames[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
int qt_monthNumberFromShortName(const QString &shortName)
{
for (unsigned int i = 0; i < sizeof(qt_shortMonthNames) / sizeof(qt_shortMonthNames[0]); ++i) {
if (shortName == QLatin1String(qt_shortMonthNames[i]))
return i + 1;
}
return -1;
}
#endif #endif
#ifndef QT_NO_DATESTRING #ifndef QT_NO_DATESTRING
static QString fmtDateTime(const QString& f, const QTime* dt = 0, const QDate* dd = 0); static QString fmtDateTime(const QString& f, const QTime* dt = 0, const QDate* dd = 0);
static void rfcDateImpl(const QString &s, QDate *dd = 0, QTime *dt = 0, int *utfcOffset = 0);
#endif #endif
/***************************************************************************** /*****************************************************************************
@ -735,6 +745,10 @@ QString QDate::longDayName(int weekday, MonthNameType type)
QLocale::ShortFormat) or QLocale().toString(date, QLocale::ShortFormat) or QLocale().toString(date,
QLocale::LongFormat). QLocale::LongFormat).
If the \a format is Qt::RFC2822Date, the string is formatted in
an \l{RFC 2822} compatible way. An example of this formatting is
"20 May 1995".
If the date is invalid, an empty string will be returned. If the date is invalid, an empty string will be returned.
\warning The Qt::ISODate format is only valid for years in the \warning The Qt::ISODate format is only valid for years in the
@ -771,6 +785,8 @@ QString QDate::toString(Qt::DateFormat f) const
.arg(y); .arg(y);
} }
#endif #endif
case Qt::RFC2822Date:
return toString(QStringLiteral("dd MMM yyyy"));
case Qt::ISODate: case Qt::ISODate:
{ {
if (year() < 0 || year() > 9999) if (year() < 0 || year() > 9999)
@ -1124,6 +1140,11 @@ QDate QDate::fromString(const QString& s, Qt::DateFormat f)
case Qt::DefaultLocaleLongDate: case Qt::DefaultLocaleLongDate:
return fromString(s, QLocale().dateFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat return fromString(s, QLocale().dateFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
: QLocale::ShortFormat)); : QLocale::ShortFormat));
case Qt::RFC2822Date: {
QDate date;
rfcDateImpl(s, &date);
return date;
}
default: default:
#ifndef QT_NO_TEXTDATE #ifndef QT_NO_TEXTDATE
case Qt::TextDate: { case Qt::TextDate: {
@ -1498,6 +1519,10 @@ int QTime::msec() const
QLocale::ShortFormat) or QLocale().toString(time, QLocale::ShortFormat) or QLocale().toString(time,
QLocale::LongFormat). QLocale::LongFormat).
If the \a format is Qt::RFC2822Date, the string is formatted in
an \l{RFC 2822} compatible way. An example of this formatting is
"23:59:20".
If the time is invalid, an empty string will be returned. If the time is invalid, an empty string will be returned.
*/ */
@ -1518,6 +1543,11 @@ QString QTime::toString(Qt::DateFormat format) const
return QLocale().toString(*this, format == Qt::DefaultLocaleLongDate ? QLocale::LongFormat return QLocale().toString(*this, format == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
: QLocale::ShortFormat); : QLocale::ShortFormat);
case Qt::RFC2822Date:
return QString::fromLatin1("%1:%2:%3")
.arg(hour(), 2, 10, QLatin1Char('0'))
.arg(minute(), 2, 10, QLatin1Char('0'))
.arg(second(), 2, 10, QLatin1Char('0'));
default: default:
case Qt::ISODate: case Qt::ISODate:
case Qt::TextDate: case Qt::TextDate:
@ -1790,6 +1820,11 @@ QTime fromStringImpl(const QString &s, Qt::DateFormat f, bool &isMidnight24)
QLocale::FormatType formatType(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat : QLocale::ShortFormat); QLocale::FormatType formatType(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat : QLocale::ShortFormat);
return QTime::fromString(s, QLocale().timeFormat(formatType)); return QTime::fromString(s, QLocale().timeFormat(formatType));
} }
case Qt::RFC2822Date: {
QTime time;
rfcDateImpl(s, 0, &time);
return time;
}
case Qt::TextDate: case Qt::TextDate:
case Qt::ISODate: case Qt::ISODate:
{ {
@ -2490,6 +2525,9 @@ void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
QLocale::ShortFormat) or QLocale().toString(datetime, QLocale::ShortFormat) or QLocale().toString(datetime,
QLocale::LongFormat). QLocale::LongFormat).
If the \a format is Qt::RFC2822Date, the string is formatted
following \l{RFC 2822}.
If the datetime is invalid, an empty string will be returned. If the datetime is invalid, an empty string will be returned.
\warning The Qt::ISODate format is only valid for years in the \warning The Qt::ISODate format is only valid for years in the
@ -2526,6 +2564,28 @@ QString QDateTime::toString(Qt::DateFormat f) const
default: default:
break; break;
} }
} else if (f == Qt::RFC2822Date) {
buf = toString(QStringLiteral("dd MMM yyyy hh:mm:ss "));
int utcOffset = d->utcOffset;
if (timeSpec() == Qt::LocalTime) {
QDateTime utc = toUTC();
utc.setTimeSpec(timeSpec());
utcOffset = utc.secsTo(*this);
}
const int offset = qAbs(utcOffset);
buf += QLatin1Char((offset == utcOffset) ? '+' : '-');
const int hour = offset / 3600;
if (hour < 10)
buf += QLatin1Char('0');
buf += QString::number(hour);
const int min = (offset - (hour * 3600)) / 60;
if (min < 10)
buf += QLatin1Char('0');
buf += QString::number(min);
} }
#ifndef QT_NO_TEXTDATE #ifndef QT_NO_TEXTDATE
else if (f == Qt::TextDate) { else if (f == Qt::TextDate) {
@ -3333,6 +3393,19 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f)
return QDateTime(date, time, ts); return QDateTime(date, time, ts);
} }
case Qt::RFC2822Date: {
QDate date;
QTime time;
int utcOffset = 0;
rfcDateImpl(s, &date, &time, &utcOffset);
if (!date.isValid() || !time.isValid())
return QDateTime();
QDateTime dateTime(date, time, Qt::UTC);
dateTime.setUtcOffset(utcOffset);
return dateTime;
}
case Qt::SystemLocaleDate: case Qt::SystemLocaleDate:
case Qt::SystemLocaleShortDate: case Qt::SystemLocaleShortDate:
case Qt::SystemLocaleLongDate: case Qt::SystemLocaleLongDate:
@ -3953,6 +4026,68 @@ static QString fmtDateTime(const QString& f, const QTime* dt, const QDate* dd)
return buf; return buf;
} }
static void rfcDateImpl(const QString &s, QDate *dd, QTime *dt, int *utcOffset)
{
int day = -1;
int month = -1;
int year = -1;
int hour = -1;
int min = -1;
int sec = -1;
int hourOffset = 0;
int minOffset = 0;
bool positiveOffset = false;
// Matches "Wdy, DD Mon YYYY HH:MM:SS ±hhmm" (Wdy, being optional)
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) {
if (dd) {
day = rex.cap(1).toInt();
month = qt_monthNumberFromShortName(rex.cap(2));
year = rex.cap(3).toInt();
}
if (dt) {
if (!rex.cap(4).isEmpty()) {
hour = rex.cap(4).toInt();
min = rex.cap(5).toInt();
sec = rex.cap(6).toInt();
}
positiveOffset = (rex.cap(7) == QStringLiteral("+"));
hourOffset = rex.cap(8).toInt();
minOffset = rex.cap(9).toInt();
}
if (utcOffset)
*utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60));
} else {
// Matches "Wdy Mon DD HH:MM:SS YYYY"
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) {
if (dd) {
month = qt_monthNumberFromShortName(rex.cap(1));
day = rex.cap(2).toInt();
year = rex.cap(6).toInt();
}
if (dt) {
if (!rex.cap(3).isEmpty()) {
hour = rex.cap(3).toInt();
min = rex.cap(4).toInt();
sec = rex.cap(5).toInt();
}
positiveOffset = (rex.cap(7) == QStringLiteral("+"));
hourOffset = rex.cap(8).toInt();
minOffset = rex.cap(9).toInt();
}
if (utcOffset)
*utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60));
}
}
if (dd)
*dd = QDate(year, month, day);
if (dt)
*dt = QTime(hour, min, sec);
}
#endif // QT_NO_DATESTRING #endif // QT_NO_DATESTRING
#ifdef Q_OS_WIN #ifdef Q_OS_WIN

View File

@ -944,6 +944,61 @@ void tst_QDate::fromStringDateFormat_data()
QTest::newRow("iso2") << QDate(1999, 11, 14).toString(Qt::ISODate) << Qt::ISODate << QDate(1999, 11, 14); QTest::newRow("iso2") << QDate(1999, 11, 14).toString(Qt::ISODate) << Qt::ISODate << QDate(1999, 11, 14);
QTest::newRow("iso3") << QString("0999-01-01") << Qt::ISODate << QDate(999, 1, 1); QTest::newRow("iso3") << QString("0999-01-01") << Qt::ISODate << QDate(999, 1, 1);
QTest::newRow("iso3b") << QString("0999-01-01") << Qt::ISODate << QDate(999, 1, 1); QTest::newRow("iso3b") << QString("0999-01-01") << Qt::ISODate << QDate(999, 1, 1);
// Test Qt::RFC2822Date format (RFC 2822).
QTest::newRow("RFC 2822") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QDate(1987, 2, 13);
QTest::newRow("RFC 2822 with day") << QString::fromLatin1("Thu, 01 Jan 1970 00:12:34 +0000")
<< Qt::RFC2822Date << QDate(1970, 1, 1);
// No timezone
QTest::newRow("RFC 2822 no timezone") << QString::fromLatin1("01 Jan 1970 00:12:34")
<< Qt::RFC2822Date << QDate(1970, 1, 1);
// No time specified
QTest::newRow("RFC 2822 date only") << QString::fromLatin1("01 Nov 2002")
<< Qt::RFC2822Date << QDate(2002, 11, 1);
QTest::newRow("RFC 2822 with day date only") << QString::fromLatin1("Fri, 01 Nov 2002")
<< Qt::RFC2822Date << QDate(2002, 11, 1);
// Test invalid month, day, year
QTest::newRow("RFC 2822 invalid month name") << QString::fromLatin1("13 Fev 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QDate();
QTest::newRow("RFC 2822 invalid day") << QString::fromLatin1("36 Fev 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QDate();
QTest::newRow("RFC 2822 invalid year") << QString::fromLatin1("13 Fev 0000 13:24:51 +0100")
<< Qt::RFC2822Date << QDate();
// Test invalid characters (should ignore invalid characters at end of string).
QTest::newRow("RFC 2822 invalid character at end") << QString::fromLatin1("01 Jan 2012 08:00:00 +0100!")
<< Qt::RFC2822Date << QDate(2012, 1, 1);
QTest::newRow("RFC 2822 invalid character at front") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000")
<< Qt::RFC2822Date << QDate();
QTest::newRow("RFC 2822 invalid character both ends") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000!")
<< Qt::RFC2822Date << QDate();
QTest::newRow("RFC 2822 invalid character at front, 2 at back") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000..")
<< Qt::RFC2822Date << QDate();
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).
QTest::newRow("RFC 850 and 1036") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100")
<< Qt::RFC2822Date << QDate(1987, 2, 13);
// No timezone
QTest::newRow("RFC 850 and 1036 no timezone") << QString::fromLatin1("Thu Jan 01 00:12:34 1970")
<< Qt::RFC2822Date << QDate(1970, 1, 1);
// No time specified
QTest::newRow("RFC 850 and 1036 date only") << QString::fromLatin1("Fri Nov 01 2002")
<< Qt::RFC2822Date << QDate(2002, 11, 1);
// Test invalid characters (should ignore invalid characters at end of string).
QTest::newRow("RFC 850 and 1036 invalid character at end") << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!")
<< Qt::RFC2822Date << QDate(2012, 1, 1);
QTest::newRow("RFC 850 and 1036 invalid character at front") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000")
<< Qt::RFC2822Date << QDate();
QTest::newRow("RFC 850 and 1036 invalid character both ends") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000!")
<< Qt::RFC2822Date << QDate();
QTest::newRow("RFC 850 and 1036 invalid character at front, 2 at back") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000..")
<< Qt::RFC2822Date << QDate();
QTest::newRow("RFC 850 and 1036 invalid character 2 at front") << QString::fromLatin1("!!Sun Jan 01 08:00:00 2012 +0000")
<< Qt::RFC2822Date << QDate();
QTest::newRow("RFC empty") << QString::fromLatin1("") << Qt::RFC2822Date << QDate();
} }
void tst_QDate::fromStringDateFormat() void tst_QDate::fromStringDateFormat()
@ -1072,6 +1127,7 @@ void tst_QDate::toStringDateFormat_data()
QTest::newRow("data3") << QDate(1974,12,1) << Qt::ISODate << QString("1974-12-01"); QTest::newRow("data3") << QDate(1974,12,1) << Qt::ISODate << QString("1974-12-01");
QTest::newRow("year < 0") << QDate(-1,1,1) << Qt::ISODate << QString(); QTest::newRow("year < 0") << QDate(-1,1,1) << Qt::ISODate << QString();
QTest::newRow("year > 9999") << QDate(-1,1,1) << Qt::ISODate << QString(); QTest::newRow("year > 9999") << QDate(-1,1,1) << Qt::ISODate << QString();
QTest::newRow("RFC2822Date") << QDate(1974,12,1) << Qt::RFC2822Date << QString("01 Dec 1974");
} }
void tst_QDate::toStringDateFormat() void tst_QDate::toStringDateFormat()

View File

@ -85,6 +85,8 @@ private slots:
void fromMSecsSinceEpoch(); void fromMSecsSinceEpoch();
void toString_isoDate_data(); void toString_isoDate_data();
void toString_isoDate(); void toString_isoDate();
void toString_rfcDate_data();
void toString_rfcDate();
void toString_enumformat(); void toString_enumformat();
void toString_strformat_data(); void toString_strformat_data();
void toString_strformat(); void toString_strformat();
@ -585,6 +587,44 @@ void tst_QDateTime::toString_isoDate()
QCOMPARE(dt.toString(Qt::ISODate), formatted); QCOMPARE(dt.toString(Qt::ISODate), formatted);
} }
void tst_QDateTime::toString_rfcDate_data()
{
QTest::addColumn<QDateTime>("dt");
QTest::addColumn<QString>("formatted");
if (europeanTimeZone) {
QTest::newRow("localtime")
<< QDateTime(QDate(1978, 11, 9), QTime(13, 28, 34))
<< QString("09 Nov 1978 13:28:34 +0100");
}
QTest::newRow("UTC")
<< QDateTime(QDate(1978, 11, 9), QTime(13, 28, 34), Qt::UTC)
<< QString("09 Nov 1978 13:28:34 +0000");
QDateTime dt(QDate(1978, 11, 9), QTime(13, 28, 34));
dt.setUtcOffset(19800);
QTest::newRow("positive OffsetFromUTC")
<< dt
<< QString("09 Nov 1978 13:28:34 +0530");
dt.setUtcOffset(-7200);
QTest::newRow("negative OffsetFromUTC")
<< dt
<< QString("09 Nov 1978 13:28:34 -0200");
QTest::newRow("invalid")
<< QDateTime(QDate(1978, 13, 9), QTime(13, 28, 34), Qt::UTC)
<< QString();
QTest::newRow("999 milliseconds UTC")
<< QDateTime(QDate(2000, 1, 1), QTime(13, 28, 34, 999), Qt::UTC)
<< QString("01 Jan 2000 13:28:34 +0000");
}
void tst_QDateTime::toString_rfcDate()
{
QFETCH(QDateTime, dt);
QFETCH(QString, formatted);
QCOMPARE(dt.toString(Qt::RFC2822Date), formatted);
}
void tst_QDateTime::toString_enumformat() void tst_QDateTime::toString_enumformat()
{ {
QDateTime dt1(QDate(1995, 5, 20), QTime(12, 34, 56)); QDateTime dt1(QDate(1995, 5, 20), QTime(12, 34, 56));
@ -1702,6 +1742,79 @@ void tst_QDateTime::fromStringDateFormat_data()
QTest::newRow("ISO .99999 of a minute (comma)") << QString::fromLatin1("2012-01-01T08:00,99999") QTest::newRow("ISO .99999 of a minute (comma)") << QString::fromLatin1("2012-01-01T08:00,99999")
<< Qt::ISODate << QDateTime(QDate(2012, 1, 1), QTime(8, 0, 59, 999), Qt::LocalTime); << Qt::ISODate << QDateTime(QDate(2012, 1, 1), QTime(8, 0, 59, 999), Qt::LocalTime);
QTest::newRow("ISO empty") << QString::fromLatin1("") << Qt::ISODate << invalidDateTime(); QTest::newRow("ISO empty") << QString::fromLatin1("") << Qt::ISODate << invalidDateTime();
// Test Qt::RFC2822Date format (RFC 2822).
QTest::newRow("RFC 2822 +0100") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC);
QTest::newRow("RFC 2822 with day +0100") << QString::fromLatin1("Fri, 13 Feb 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC);
QTest::newRow("RFC 2822 -0100") << QString::fromLatin1("13 Feb 1987 13:24:51 -0100")
<< Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(14, 24, 51), Qt::UTC);
QTest::newRow("RFC 2822 with day -0100") << QString::fromLatin1("Fri, 13 Feb 1987 13:24:51 -0100")
<< Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(14, 24, 51), Qt::UTC);
QTest::newRow("RFC 2822 +0000") << QString::fromLatin1("01 Jan 1970 00:12:34 +0000")
<< Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
QTest::newRow("RFC 2822 with day +0000") << QString::fromLatin1("Thu, 01 Jan 1970 00:12:34 +0000")
<< Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
QTest::newRow("RFC 2822 +0000") << QString::fromLatin1("01 Jan 1970 00:12:34 +0000")
<< Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
QTest::newRow("RFC 2822 with day +0000") << QString::fromLatin1("Thu, 01 Jan 1970 00:12:34 +0000")
<< Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
// No timezone assume UTC
QTest::newRow("RFC 2822 no timezone") << QString::fromLatin1("01 Jan 1970 00:12:34")
<< Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
// No time specified
QTest::newRow("RFC 2822 date only") << QString::fromLatin1("01 Nov 2002")
<< Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 2822 with day date only") << QString::fromLatin1("Fri, 01 Nov 2002")
<< Qt::RFC2822Date << invalidDateTime();
// Test invalid month, day, year
QTest::newRow("RFC 2822 invalid month name") << QString::fromLatin1("13 Fev 1987 13:24:51 +0100")
<< Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 2822 invalid day") << QString::fromLatin1("36 Fev 1987 13:24:51 +0100")
<< Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 2822 invalid year") << QString::fromLatin1("13 Fev 0000 13:24:51 +0100")
<< Qt::RFC2822Date << invalidDateTime();
// Test invalid characters (should ignore invalid characters at end of string).
QTest::newRow("RFC 2822 invalid character at end") << QString::fromLatin1("01 Jan 2012 08:00:00 +0100!")
<< Qt::RFC2822Date << QDateTime(QDate(2012, 1, 1), QTime(7, 0, 0, 0), Qt::UTC);
QTest::newRow("RFC 2822 invalid character at front") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000")
<< Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 2822 invalid character both ends") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000!")
<< Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 2822 invalid character at front, 2 at back") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000..")
<< Qt::RFC2822Date << invalidDateTime();
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).
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")
<< Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(14, 24, 51), Qt::UTC);
QTest::newRow("RFC 850 and 1036 +0000") << QString::fromLatin1("Thu Jan 01 00:12:34 1970 +0000")
<< Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
QTest::newRow("RFC 850 and 1036 +0000") << QString::fromLatin1("Thu Jan 01 00:12:34 1970 +0000")
<< Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
// No timezone assume UTC
QTest::newRow("RFC 850 and 1036 no timezone") << QString::fromLatin1("Thu Jan 01 00:12:34 1970")
<< Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
// No time specified
QTest::newRow("RFC 850 and 1036 date only") << QString::fromLatin1("Fri Nov 01 2002")
<< Qt::RFC2822Date << invalidDateTime();
// Test invalid characters (should ignore invalid characters at end of string).
QTest::newRow("RFC 850 and 1036 invalid character at end") << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!")
<< Qt::RFC2822Date << QDateTime(QDate(2012, 1, 1), QTime(7, 0, 0, 0), Qt::UTC);
QTest::newRow("RFC 850 and 1036 invalid character at front") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000")
<< Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 850 and 1036 invalid character both ends") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000!")
<< Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 850 and 1036 invalid character at front, 2 at back") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000..")
<< Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 850 and 1036 invalid character 2 at front") << QString::fromLatin1("!!Sun Jan 01 08:00:00 2012 +0000")
<< Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC empty") << QString::fromLatin1("") << Qt::RFC2822Date << invalidDateTime();
} }
void tst_QDateTime::fromStringDateFormat() void tst_QDateTime::fromStringDateFormat()

View File

@ -600,6 +600,59 @@ void tst_QTime::fromStringDateFormat_data()
QTest::newRow("IsoDate - data2") << QString("19:03:54.998601") << Qt::ISODate << QTime(19, 3, 54, 999); QTest::newRow("IsoDate - data2") << QString("19:03:54.998601") << Qt::ISODate << QTime(19, 3, 54, 999);
QTest::newRow("IsoDate - data3") << QString("19:03:54.999601") << Qt::ISODate << QTime(19, 3, 54, 999); QTest::newRow("IsoDate - data3") << QString("19:03:54.999601") << Qt::ISODate << QTime(19, 3, 54, 999);
QTest::newRow("IsoDate - minute fraction midnight") << QString("24:00,0") << Qt::ISODate << QTime(0, 0, 0, 0); QTest::newRow("IsoDate - minute fraction midnight") << QString("24:00,0") << Qt::ISODate << QTime(0, 0, 0, 0);
// Test Qt::RFC2822Date format (RFC 2822).
QTest::newRow("RFC 2822") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QTime(13, 24, 51);
QTest::newRow("RFC 2822 with day") << QString::fromLatin1("Thu, 01 Jan 1970 00:12:34 +0000")
<< Qt::RFC2822Date << QTime(0, 12, 34);
// No timezone
QTest::newRow("RFC 2822 no timezone") << QString::fromLatin1("01 Jan 1970 00:12:34")
<< Qt::RFC2822Date << QTime(0, 12, 34);
// No time specified
QTest::newRow("RFC 2822 date only") << QString::fromLatin1("01 Nov 2002")
<< Qt::RFC2822Date << invalidTime();
QTest::newRow("RFC 2822 with day date only") << QString::fromLatin1("Fri, 01 Nov 2002")
<< Qt::RFC2822Date << invalidTime();
// Test invalid month, day, year
QTest::newRow("RFC 2822 invalid month name") << QString::fromLatin1("13 Fev 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QTime(13, 24, 51);
QTest::newRow("RFC 2822 invalid day") << QString::fromLatin1("36 Fev 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QTime(13, 24, 51);
QTest::newRow("RFC 2822 invalid year") << QString::fromLatin1("13 Fev 0000 13:24:51 +0100")
<< Qt::RFC2822Date << QTime(13, 24, 51);
// Test invalid characters (should ignore invalid characters at end of string).
QTest::newRow("RFC 2822 invalid character at end") << QString::fromLatin1("01 Jan 2012 08:00:00 +0100!")
<< Qt::RFC2822Date << QTime(8, 0, 0);
QTest::newRow("RFC 2822 invalid character at front") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000")
<< Qt::RFC2822Date << invalidTime();
QTest::newRow("RFC 2822 invalid character both ends") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000!")
<< Qt::RFC2822Date << invalidTime();
QTest::newRow("RFC 2822 invalid character at front, 2 at back") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000..")
<< Qt::RFC2822Date << invalidTime();
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).
QTest::newRow("RFC 850 and 1036") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100")
<< Qt::RFC2822Date << QTime(13, 24, 51);
// No timezone
QTest::newRow("RFC 850 and 1036 no timezone") << QString::fromLatin1("Thu Jan 01 00:12:34 1970")
<< Qt::RFC2822Date << QTime(0, 12, 34);
// No time specified
QTest::newRow("RFC 850 and 1036 date only") << QString::fromLatin1("Fri Nov 01 2002")
<< Qt::RFC2822Date << invalidTime();
// Test invalid characters (should ignore invalid characters at end of string).
QTest::newRow("RFC 850 and 1036 invalid character at end") << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!")
<< Qt::RFC2822Date << QTime(8, 0, 0);
QTest::newRow("RFC 850 and 1036 invalid character at front") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000")
<< Qt::RFC2822Date << invalidTime();
QTest::newRow("RFC 850 and 1036 invalid character both ends") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000!")
<< Qt::RFC2822Date << invalidTime();
QTest::newRow("RFC 850 and 1036 invalid character at front, 2 at back") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000..")
<< Qt::RFC2822Date << invalidTime();
QTest::newRow("RFC empty") << QString::fromLatin1("") << Qt::RFC2822Date << invalidTime();
} }
void tst_QTime::fromStringDateFormat() void tst_QTime::fromStringDateFormat()
@ -626,6 +679,7 @@ void tst_QTime::toStringDateFormat_data()
QTest::newRow("ISO 10:12:34.001") << QTime(10, 12, 34, 001) << Qt::ISODate << QString("10:12:34.001"); QTest::newRow("ISO 10:12:34.001") << QTime(10, 12, 34, 001) << Qt::ISODate << QString("10:12:34.001");
QTest::newRow("Text 10:12:34.999") << QTime(10, 12, 34, 999) << Qt::TextDate << QString("10:12:34.999"); QTest::newRow("Text 10:12:34.999") << QTime(10, 12, 34, 999) << Qt::TextDate << QString("10:12:34.999");
QTest::newRow("ISO 10:12:34.999") << QTime(10, 12, 34, 999) << Qt::ISODate << QString("10:12:34.999"); QTest::newRow("ISO 10:12:34.999") << QTime(10, 12, 34, 999) << Qt::ISODate << QString("10:12:34.999");
QTest::newRow("RFC2822Date") << QTime(10, 12, 34, 999) << Qt::RFC2822Date << QString("10:12:34");
} }
void tst_QTime::toStringDateFormat() void tst_QTime::toStringDateFormat()