Teach QDateTimeParser some common time-zone offset formats
Fixes: QTBUG-83687 Fixes: QTBUG-83844 Pick-to: 5.15 Change-Id: Ia1c827017b93cf8277aa5a0266805d773d2d9818 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
ed4c1b4e90
commit
bed25fdf60
@ -2382,7 +2382,7 @@ static QString qt_tzname(QDateTimePrivate::DaylightStatus daylightStatus)
|
||||
#endif // Q_OS_WIN
|
||||
}
|
||||
|
||||
#if QT_CONFIG(datetimeparser) && QT_CONFIG(timezone)
|
||||
#if QT_CONFIG(datetimeparser)
|
||||
/*
|
||||
\internal
|
||||
Implemented here to share qt_tzname()
|
||||
@ -2400,7 +2400,7 @@ int QDateTimeParser::startsWithLocalTimeZone(const QStringRef name)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif // datetimeparser && timezone
|
||||
#endif // datetimeparser
|
||||
|
||||
// Calls the platform variant of mktime for the given date, time and daylightStatus,
|
||||
// and updates the date, time, daylightStatus and abbreviation with the returned values
|
||||
|
@ -218,9 +218,11 @@ int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
|
||||
{
|
||||
const SectionNode &sn = sectionNode(s);
|
||||
switch (sn.type) {
|
||||
#if QT_CONFIG(timezone)
|
||||
case TimeZoneSection:
|
||||
#if QT_CONFIG(timezone)
|
||||
return QTimeZone::MaxUtcOffsetSecs;
|
||||
#else
|
||||
return +14 * 3600; // NB: copied from QTimeZone
|
||||
#endif
|
||||
case Hour24Section:
|
||||
case Hour12Section:
|
||||
@ -263,8 +265,11 @@ int QDateTimeParser::absoluteMin(int s) const
|
||||
{
|
||||
const SectionNode &sn = sectionNode(s);
|
||||
switch (sn.type) {
|
||||
case TimeZoneSection:
|
||||
#if QT_CONFIG(timezone)
|
||||
case TimeZoneSection: return QTimeZone::MinUtcOffsetSecs;
|
||||
return QTimeZone::MinUtcOffsetSecs;
|
||||
#else
|
||||
return -14 * 3600; // NB: copied from QTimeZone
|
||||
#endif
|
||||
case Hour24Section:
|
||||
case Hour12Section:
|
||||
@ -1200,24 +1205,29 @@ QDateTimeParser::scanString(const QDateTime &defaultValue,
|
||||
case TimeZoneSection:
|
||||
current = &zoneOffset;
|
||||
if (sect.used > 0) {
|
||||
#if QT_CONFIG(timezone) // Synchronize with what findTimeZone() found:
|
||||
// Synchronize with what findTimeZone() found:
|
||||
QStringRef zoneName = input->midRef(pos, sect.used);
|
||||
Q_ASSERT(!zoneName.isEmpty()); // sect.used > 0
|
||||
const QByteArray latinZone(zoneName == QLatin1String("Z")
|
||||
? QByteArray("UTC") : zoneName.toLatin1());
|
||||
if (latinZone.startsWith("UTC") &&
|
||||
(latinZone.size() == 3 || latinZone.at(3) == '+' || latinZone.at(3) == '-' )) {
|
||||
timeZone = QTimeZone(sect.value);
|
||||
|
||||
const QStringRef offsetStr = zoneName.startsWith(QLatin1String("UTC"))
|
||||
? zoneName.mid(3) : zoneName;
|
||||
const bool isUtcOffset = offsetStr.startsWith(QLatin1Char('+'))
|
||||
|| offsetStr.startsWith(QLatin1Char('-'));
|
||||
const bool isUtc = zoneName == QLatin1String("Z")
|
||||
|| zoneName == QLatin1String("UTC");
|
||||
|
||||
if (isUtc || isUtcOffset) {
|
||||
tspec = sect.value ? Qt::OffsetFromUTC : Qt::UTC;
|
||||
} else {
|
||||
timeZone = QTimeZone(latinZone);
|
||||
#if QT_CONFIG(timezone)
|
||||
timeZone = QTimeZone(zoneName.toLatin1());
|
||||
tspec = timeZone.isValid()
|
||||
? Qt::TimeZone
|
||||
: (Q_ASSERT(startsWithLocalTimeZone(zoneName)), Qt::LocalTime);
|
||||
}
|
||||
#else
|
||||
tspec = Qt::LocalTime;
|
||||
tspec = Qt::LocalTime;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Hour24Section: current = &hour; break;
|
||||
@ -1637,6 +1647,111 @@ int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex
|
||||
return index < 0 ? index : index + startDay;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Return's .value is UTC offset in seconds.
|
||||
The caller must verify that the offset is within a valid range.
|
||||
*/
|
||||
QDateTimeParser::ParsedSection QDateTimeParser::findUtcOffset(QStringRef str) const
|
||||
{
|
||||
const bool startsWithUtc = str.startsWith(QLatin1String("UTC"));
|
||||
// Get rid of UTC prefix if it exists
|
||||
if (startsWithUtc)
|
||||
str = str.mid(3);
|
||||
|
||||
const bool negativeSign = str.startsWith(QLatin1Char('-'));
|
||||
// Must start with a sign:
|
||||
if (!negativeSign && !str.startsWith(QLatin1Char('+')))
|
||||
return ParsedSection();
|
||||
str = str.mid(1); // drop sign
|
||||
|
||||
const int colonPosition = str.indexOf(QLatin1Char(':'));
|
||||
// Colon that belongs to offset is at most at position 2 (hh:mm)
|
||||
bool hasColon = (colonPosition >= 0 && colonPosition < 3);
|
||||
|
||||
// We deal only with digits at this point (except ':'), so collect them
|
||||
const int digits = hasColon ? colonPosition + 3 : 4;
|
||||
int i = 0;
|
||||
for (const int offsetLength = qMin(digits, str.size()); i < offsetLength; ++i) {
|
||||
if (i != colonPosition && !str.at(i).isDigit())
|
||||
break;
|
||||
}
|
||||
const int hoursLength = qMin(i, hasColon ? colonPosition : 2);
|
||||
if (hoursLength < 1)
|
||||
return ParsedSection();
|
||||
// Field either ends with hours or also has two digits of minutes
|
||||
if (i < digits) {
|
||||
// Only allow single-digit hours with UTC prefix or :mm suffix
|
||||
if (!startsWithUtc && hoursLength != 2)
|
||||
return ParsedSection();
|
||||
i = hoursLength;
|
||||
hasColon = false;
|
||||
}
|
||||
str.truncate(i); // The rest of the string is not part of the UTC offset
|
||||
|
||||
bool isInt = false;
|
||||
const int hours = str.mid(0, hoursLength).toInt(&isInt);
|
||||
if (!isInt)
|
||||
return ParsedSection();
|
||||
const QStringRef minutesStr = str.mid(hasColon ? colonPosition + 1 : 2, 2);
|
||||
const int minutes = minutesStr.isEmpty() ? 0 : minutesStr.toInt(&isInt);
|
||||
if (!isInt)
|
||||
return ParsedSection();
|
||||
|
||||
// Keep in sync with QTimeZone::maxUtcOffset hours (14 at most). Also, user
|
||||
// could be in the middle of updating the offset (e.g. UTC+14:23) which is
|
||||
// an intermediate state
|
||||
const State status = (hours > 14 || minutes >= 60) ? Invalid
|
||||
: (hours == 14 && minutes > 0) ? Intermediate : Acceptable;
|
||||
|
||||
int offset = 3600 * hours + 60 * minutes;
|
||||
if (negativeSign)
|
||||
offset = -offset;
|
||||
|
||||
// Used: UTC, sign, hours, colon, minutes
|
||||
const int usedSymbols = (startsWithUtc ? 3 : 0) + 1 + hoursLength + (hasColon ? 1 : 0)
|
||||
+ minutesStr.size();
|
||||
|
||||
return ParsedSection(status, offset, usedSymbols);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Return's .value is zone's offset, zone time - UTC time, in seconds.
|
||||
The caller must verify that the offset is within a valid range.
|
||||
See QTimeZonePrivate::isValidId() for the format of zone names.
|
||||
*/
|
||||
QDateTimeParser::ParsedSection
|
||||
QDateTimeParser::findTimeZoneName(QStringRef str, const QDateTime &when) const
|
||||
{
|
||||
int index = startsWithLocalTimeZone(str);
|
||||
if (index > 0) // won't actually use the offset, but need it to be valid
|
||||
return ParsedSection(Acceptable, when.toLocalTime().offsetFromUtc(), index);
|
||||
|
||||
#if QT_CONFIG(timezone)
|
||||
const int size = str.length();
|
||||
|
||||
// Collect up plausibly-valid characters; let QTimeZone work out what's
|
||||
// truly valid.
|
||||
for (; index < size; ++index) {
|
||||
const QChar here = str[index];
|
||||
if (here >= 127 || (!here.isLetterOrNumber() && !QLatin1String("/-_.+:").contains(here)))
|
||||
break;
|
||||
}
|
||||
|
||||
while (index > 0) {
|
||||
str.truncate(index);
|
||||
QTimeZone zone(str.toLatin1());
|
||||
if (zone.isValid())
|
||||
return ParsedSection(Acceptable, zone.offsetFromUtc(when), index);
|
||||
index--; // maybe we collected too much ...
|
||||
}
|
||||
#endif
|
||||
return ParsedSection();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
@ -1647,55 +1762,21 @@ QDateTimeParser::ParsedSection
|
||||
QDateTimeParser::findTimeZone(QStringRef str, const QDateTime &when,
|
||||
int maxVal, int minVal) const
|
||||
{
|
||||
#if QT_CONFIG(timezone)
|
||||
int index = startsWithLocalTimeZone(str);
|
||||
int offset;
|
||||
ParsedSection section = findUtcOffset(str);
|
||||
if (section.used <= 0) // if nothing used, try time zone parsing
|
||||
section = findTimeZoneName(str, when);
|
||||
// It can be a well formed time zone specifier, but with value out of range
|
||||
if (section.state == Acceptable && (section.value < minVal || section.value > maxVal))
|
||||
section.state = Intermediate;
|
||||
if (section.used > 0)
|
||||
return section;
|
||||
|
||||
if (index > 0) {
|
||||
// We won't actually use this, but we need a valid return:
|
||||
offset = QDateTime(when.date(), when.time(), Qt::LocalTime).offsetFromUtc();
|
||||
} else {
|
||||
int size = str.length();
|
||||
offset = std::numeric_limits<int>::max(); // deliberately out of range
|
||||
Q_ASSERT(offset > QTimeZone::MaxUtcOffsetSecs); // cf. absoluteMax()
|
||||
// Check if string is UTC or alias to UTC, after all other options
|
||||
if (str.startsWith(QLatin1String("UTC")))
|
||||
return ParsedSection(Acceptable, 0, 3);
|
||||
if (str.startsWith(QLatin1Char('Z')))
|
||||
return ParsedSection(Acceptable, 0, 1);
|
||||
|
||||
// Collect up plausibly-valid characters; let QTimeZone work out what's truly valid.
|
||||
while (index < size) {
|
||||
const auto here = str[index].unicode();
|
||||
if (here < 127
|
||||
&& (QChar::isLetterOrNumber(here)
|
||||
|| here == '/' || here == '-'
|
||||
|| here == '_' || here == '.'
|
||||
|| here == '+' || here == ':'))
|
||||
index++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
break;
|
||||
}
|
||||
index--; // maybe we collected too much ...
|
||||
}
|
||||
}
|
||||
|
||||
if (index > 0 && maxVal >= offset && offset >= minVal)
|
||||
return ParsedSection(Acceptable, offset, index);
|
||||
|
||||
#else // timezone
|
||||
Q_UNUSED(str);
|
||||
Q_UNUSED(when);
|
||||
Q_UNUSED(maxVal);
|
||||
Q_UNUSED(minVal);
|
||||
#endif
|
||||
return ParsedSection();
|
||||
}
|
||||
|
||||
|
@ -220,12 +220,12 @@ private:
|
||||
int year, QString *monthName = nullptr, int *used = nullptr) const;
|
||||
int findDay(const QString &str1, int intDaystart, int sectionIndex,
|
||||
QString *dayName = nullptr, int *used = nullptr) const;
|
||||
ParsedSection findUtcOffset(QStringRef str) const;
|
||||
ParsedSection findTimeZoneName(QStringRef str, const QDateTime &when) const;
|
||||
ParsedSection findTimeZone(QStringRef str, const QDateTime &when,
|
||||
int maxVal, int minVal) const;
|
||||
#if QT_CONFIG(timezone)
|
||||
// Implemented in qdatetime.cpp:
|
||||
static int startsWithLocalTimeZone(const QStringRef name);
|
||||
#endif
|
||||
|
||||
enum AmPmFinder {
|
||||
Neither = -1,
|
||||
|
@ -2511,11 +2511,136 @@ void tst_QDateTime::fromStringStringFormat_data()
|
||||
QTest::newRow("data13") << QString("30.02.2004") << QString("dd.MM.yyyy") << invalidDateTime();
|
||||
QTest::newRow("data14") << QString("32.01.2004") << QString("dd.MM.yyyy") << invalidDateTime();
|
||||
QTest::newRow("data15") << QString("Thu January 2004") << QString("ddd MMMM yyyy") << QDateTime(QDate(2004, 1, 1), QTime());
|
||||
#if QT_CONFIG(timezone)
|
||||
// Qt::UTC and Qt::OffsetFromUTC not supported without timezone: QTBUG-83844
|
||||
QTest::newRow("data16") << QString("2005-06-28T07:57:30.001Z")
|
||||
<< QString("yyyy-MM-ddThh:mm:ss.zt")
|
||||
<< QDateTime(QDate(2005, 06, 28), QTime(07, 57, 30, 1), Qt::UTC);
|
||||
QTest::newRow("utc-time-spec-as:UTC+0")
|
||||
<< QString("2005-06-28T07:57:30.001UTC+0") << QString("yyyy-MM-ddThh:mm:ss.zt")
|
||||
<< QDateTime(QDate(2005, 6, 28), QTime(7, 57, 30, 1), Qt::UTC);
|
||||
QTest::newRow("utc-time-spec-as:UTC-0")
|
||||
<< QString("2005-06-28T07:57:30.001UTC-0") << QString("yyyy-MM-ddThh:mm:ss.zt")
|
||||
<< QDateTime(QDate(2005, 6, 28), QTime(7, 57, 30, 1), Qt::UTC);
|
||||
QTest::newRow("offset-from-utc:UTC+1")
|
||||
<< QString("2001-09-13T07:33:01.001 UTC+1") << QString("yyyy-MM-ddThh:mm:ss.z t")
|
||||
<< QDateTime(QDate(2001, 9, 13), QTime(7, 33, 1, 1), Qt::OffsetFromUTC, 3600);
|
||||
QTest::newRow("offset-from-utc:UTC-11:01")
|
||||
<< QString("2008-09-13T07:33:01.001 UTC-11:01") << QString("yyyy-MM-ddThh:mm:ss.z t")
|
||||
<< QDateTime(QDate(2008, 9, 13), QTime(7, 33, 1, 1), Qt::OffsetFromUTC, -39660);
|
||||
QTest::newRow("offset-from-utc:UTC+02:57")
|
||||
<< QString("2001-09-15T09:33:01.001UTC+02:57") << QString("yyyy-MM-ddThh:mm:ss.zt")
|
||||
<< QDateTime(QDate(2001, 9, 15), QTime(9, 33, 1, 1), Qt::OffsetFromUTC, 10620);
|
||||
QTest::newRow("offset-from-utc:-03:00") // RFC 3339 offset format
|
||||
<< QString("2001-09-15T09:33:01.001-03:00") << QString("yyyy-MM-ddThh:mm:ss.zt")
|
||||
<< QDateTime(QDate(2001, 9, 15), QTime(9, 33, 1, 1), Qt::OffsetFromUTC, -10800);
|
||||
QTest::newRow("offset-from-utc:+0205") // ISO 8601 basic offset format
|
||||
<< QString("2001-09-15T09:33:01.001+0205") << QString("yyyy-MM-ddThh:mm:ss.zt")
|
||||
<< QDateTime(QDate(2001, 9, 15), QTime(9, 33, 1, 1), Qt::OffsetFromUTC, 7500);
|
||||
QTest::newRow("offset-from-utc:-0401") // ISO 8601 basic offset format
|
||||
<< QString("2001-09-15T09:33:01.001-0401") << QString("yyyy-MM-ddThh:mm:ss.zt")
|
||||
<< QDateTime(QDate(2001, 9, 15), QTime(9, 33, 1, 1), Qt::OffsetFromUTC, -14460);
|
||||
QTest::newRow("offset-from-utc:+10") // ISO 8601 basic (hour-only) offset format
|
||||
<< QString("2001-09-15T09:33:01.001 +10") << QString("yyyy-MM-ddThh:mm:ss.z t")
|
||||
<< QDateTime(QDate(2001, 9, 15), QTime(9, 33, 1, 1), Qt::OffsetFromUTC, 36000);
|
||||
QTest::newRow("offset-from-utc:UTC+10:00") // Time-spec specifier at the beginning
|
||||
<< QString("UTC+10:00 2008-10-13T07:33") << QString("t yyyy-MM-ddThh:mm")
|
||||
<< QDateTime(QDate(2008, 10, 13), QTime(7, 33), Qt::OffsetFromUTC, 36000);
|
||||
QTest::newRow("offset-from-utc:UTC-03:30") // Time-spec specifier in the middle
|
||||
<< QString("2008-10-13 UTC-03:30 11.50") << QString("yyyy-MM-dd t hh.mm")
|
||||
<< QDateTime(QDate(2008, 10, 13), QTime(11, 50), Qt::OffsetFromUTC, -12600);
|
||||
QTest::newRow("offset-from-utc:UTC-2") // Time-spec specifier joined with text/time
|
||||
<< QString("2008-10-13 UTC-2Z11.50") << QString("yyyy-MM-dd tZhh.mm")
|
||||
<< QDateTime(QDate(2008, 10, 13), QTime(11, 50), Qt::OffsetFromUTC, -7200);
|
||||
QTest::newRow("offset-from-utc:followed-by-colon")
|
||||
<< QString("2008-10-13 UTC-0100:11.50") << QString("yyyy-MM-dd t:hh.mm")
|
||||
<< QDateTime(QDate(2008, 10, 13), QTime(11, 50), Qt::OffsetFromUTC, -3600);
|
||||
QTest::newRow("offset-from-utc:late-colon")
|
||||
<< QString("2008-10-13 UTC+05T:11.50") << QString("yyyy-MM-dd tT:hh.mm")
|
||||
<< QDateTime(QDate(2008, 10, 13), QTime(11, 50), Qt::OffsetFromUTC, 18000);
|
||||
QTest::newRow("offset-from-utc:merged-with-time")
|
||||
<< QString("2008-10-13 UTC+010011.50") << QString("yyyy-MM-dd thh.mm")
|
||||
<< QDateTime(QDate(2008, 10, 13), QTime(11, 50), Qt::OffsetFromUTC, 3600);
|
||||
QTest::newRow("offset-from-utc:double-colon-delimiter")
|
||||
<< QString("2008-10-13 UTC+12::11.50") << QString("yyyy-MM-dd t::hh.mm")
|
||||
<< QDateTime(QDate(2008, 10, 13), QTime(11, 50), Qt::OffsetFromUTC, 43200);
|
||||
QTest::newRow("offset-from-utc:3-digit-with-colon")
|
||||
<< QString("2008-10-13 -4:30 11.50") << QString("yyyy-MM-dd t hh.mm")
|
||||
<< QDateTime(QDate(2008, 10, 13), QTime(11, 50), Qt::OffsetFromUTC, -16200);
|
||||
QTest::newRow("offset-from-utc:merged-with-time")
|
||||
<< QString("2008-10-13 UTC+010011.50") << QString("yyyy-MM-dd thh.mm")
|
||||
<< QDateTime(QDate(2008, 10, 13), QTime(11, 50), Qt::OffsetFromUTC, 3600);
|
||||
QTest::newRow("offset-from-utc:with-colon-merged-with-time")
|
||||
<< QString("2008-10-13 UTC+01:0011.50") << QString("yyyy-MM-dd thh.mm")
|
||||
<< QDateTime(QDate(2008, 10, 13), QTime(11, 50), Qt::OffsetFromUTC, 3600);
|
||||
QTest::newRow("invalid-offset-from-utc:out-of-range")
|
||||
<< QString("2001-09-15T09:33:01.001-50") << QString("yyyy-MM-ddThh:mm:ss.zt")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:single-digit-format")
|
||||
<< QString("2001-09-15T09:33:01.001+5") << QString("yyyy-MM-ddThh:mm:ss.zt")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:three-digit-format")
|
||||
<< QString("2001-09-15T09:33:01.001-701") << QString("yyyy-MM-ddThh:mm:ss.zt")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:three-digit-minutes")
|
||||
<< QString("2001-09-15T09:33:01.001+11:570") << QString("yyyy-MM-ddThh:mm:ss.zt")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:single-digit-minutes")
|
||||
<< QString("2001-09-15T09:33:01.001+11:5") << QString("yyyy-MM-ddThh:mm:ss.zt")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:invalid-sign-symbol")
|
||||
<< QString("2001-09-15T09:33:01.001 ~11:30") << QString("yyyy-MM-ddThh:mm:ss.z t")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:symbol-in-hours")
|
||||
<< QString("2001-09-15T09:33:01.001 UTC+o8:30") << QString("yyyy-MM-ddThh:mm:ss.z t")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:symbol-in-minutes")
|
||||
<< QString("2001-09-15T09:33:01.001 UTC+08:3i") << QString("yyyy-MM-ddThh:mm:ss.z t")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:UTC+123") // Invalid offset (UTC and 3 digit format)
|
||||
<< QString("2001-09-15T09:33:01.001 UTC+123") << QString("yyyy-MM-ddThh:mm:ss.z t")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:UTC+00005") // Invalid offset with leading zeroes
|
||||
<< QString("2001-09-15T09:33:01.001 UTC+00005") << QString("yyyy-MM-ddThh:mm:ss.z t")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:three-digit-with-colon-delimiter")
|
||||
<< QString("2008-10-13 +123:11.50") << QString("yyyy-MM-dd t:hh.mm")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:double-colon-as-part-of-offset")
|
||||
<< QString("2008-10-13 UTC+12::11.50") << QString("yyyy-MM-dd thh.mm")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:single-colon-as-part-of-offset")
|
||||
<< QString("2008-10-13 UTC+12::11.50") << QString("yyyy-MM-dd t:hh.mm")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:starts-with-colon")
|
||||
<< QString("2008-10-13 UTC+:59 11.50") << QString("yyyy-MM-dd t hh.mm")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:empty-offset")
|
||||
<< QString("2008-10-13 UTC+ 11.50") << QString("yyyy-MM-dd t hh.mm")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:time-section-instead-of-offset")
|
||||
<< QString("2008-10-13 UTC+11.50") << QString("yyyy-MM-dd thh.mm")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:missing-minutes-if-colon")
|
||||
<< QString("2008-10-13 +05: 11.50") << QString("yyyy-MM-dd t hh.mm")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:1-digit-minutes-if-colon")
|
||||
<< QString("2008-10-13 UTC+05:1 11.50") << QString("yyyy-MM-dd t hh.mm")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-time-spec:random-symbol")
|
||||
<< QString("2001-09-15T09:33:01.001 $") << QString("yyyy-MM-ddThh:mm:ss.z t")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-time-spec:random-digit")
|
||||
<< QString("2001-09-15T09:33:01.001 1") << QString("yyyy-MM-ddThh:mm:ss.z t")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:merged-with-time")
|
||||
<< QString("2008-10-13 UTC+0111.50") << QString("yyyy-MM-dd thh.mm")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-offset-from-utc:with-colon-3-digit-merged-with-time")
|
||||
<< QString("2008-10-13 UTC+01:011.50") << QString("yyyy-MM-dd thh.mm")
|
||||
<< invalidDateTime();
|
||||
QTest::newRow("invalid-time-spec:empty")
|
||||
<< QString("2001-09-15T09:33:01.001 ") << QString("yyyy-MM-ddThh:mm:ss.z t")
|
||||
<< invalidDateTime();
|
||||
#if QT_CONFIG(timezone)
|
||||
QTimeZone southBrazil("America/Sao_Paulo");
|
||||
if (southBrazil.isValid()) {
|
||||
QTest::newRow("spring-forward-midnight")
|
||||
@ -2556,6 +2681,8 @@ void tst_QDateTime::fromStringStringFormat()
|
||||
if (expected.timeSpec() == Qt::TimeZone)
|
||||
QCOMPARE(dt.timeZone(), expected.timeZone());
|
||||
#endif
|
||||
// OffsetFromUTC needs an offset check - we may as well do it for all:
|
||||
QCOMPARE(dt.offsetFromUtc(), expected.offsetFromUtc());
|
||||
}
|
||||
QCOMPARE(dt, expected);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user