Check QDT's local time abbreviation as well as the qTzName()s

Since QDateTime uses some fall-backs if qTzName() doesn't give it
something useful (as happens on MS-Win when local time is UTC),
QDateTimeParser should check the result of those fall-backs as well as
the qTzName()s when checking for local-time as zone.

Change-Id: Ic809b7e44cd0c83fb076b24c27547268345fa379
Reviewed-by: Konrad Kujawa <konrad.kujawa@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
(cherry picked from commit c888e3922d73df791f0f31553536abf03b241a65)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Edward Welbourne 2023-07-13 14:43:55 +02:00 committed by Qt Cherry-pick Bot
parent bd45bd2769
commit 89db6ceef0

View File

@ -1183,13 +1183,18 @@ static QTime actualTime(QDateTimeParser::Sections known,
/*
\internal
*/
static int startsWithLocalTimeZone(QStringView name)
static int startsWithLocalTimeZone(QStringView name, const QDateTime &when)
{
// On MS-Win, at least when system zone is UTC, the tzname[]s may be empty.
for (int i = 0; i < 2; ++i) {
const QString zone(qTzName(i));
if (name.startsWith(zone))
if (!zone.isEmpty() && name.startsWith(zone))
return zone.size();
}
// Mimic what QLocale::toString() would have used, to ensure round-trips work:
const QString local = QDateTime(when.date(), when.time()).timeZoneAbbreviation();
if (name.startsWith(local))
return local.size();
return 0;
}
@ -1235,14 +1240,13 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, bool fixup) const
int *current = nullptr;
int zoneOffset; // Needed to serve as *current when setting zone
const SectionNode sn = sectionNodes.at(index);
ParsedSection sect;
{
const QDateTime usedDateTime = ([=]() {
const QDate date = actualDate(isSet, calendar, year, year2digits,
month, day, dayofweek);
const QTime time = actualTime(isSet, hour, hour12, ampm, minute, second, msec);
sect = parseSection(QDateTime(date, time, timeZone), index, pos);
}
return QDateTime(date, time, timeZone);
})();
ParsedSection sect = parseSection(usedDateTime, index, pos);
QDTPDEBUG << "sectionValue" << sn.name() << m_text
<< "pos" << pos << "used" << sect.used << stateName(sect.state);
@ -1283,7 +1287,7 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, bool fixup) const
if (namedZone.isValid()) {
timeZone = namedZone;
} else {
Q_ASSERT(startsWithLocalTimeZone(zoneName));
Q_ASSERT(startsWithLocalTimeZone(zoneName, usedDateTime));
timeZone = QTimeZone::LocalTime;
}
#else
@ -1793,7 +1797,7 @@ QDateTimeParser::ParsedSection QDateTimeParser::findUtcOffset(QStringView str, i
QDateTimeParser::ParsedSection
QDateTimeParser::findTimeZoneName(QStringView str, const QDateTime &when) const
{
const int systemLength = startsWithLocalTimeZone(str);
const int systemLength = startsWithLocalTimeZone(str, when);
#if QT_CONFIG(timezone)
// Collect up plausibly-valid characters; let QTimeZone work out what's
// truly valid.