summaryrefslogtreecommitdiffstats
path: root/src/corelib/time/qdatetimeparser.cpp
diff options
Diffstat (limited to 'src/corelib/time/qdatetimeparser.cpp')
-rw-r--r--src/corelib/time/qdatetimeparser.cpp46
1 files changed, 40 insertions, 6 deletions
diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp
index 31e010de74d..3e8e6ac77ea 100644
--- a/src/corelib/time/qdatetimeparser.cpp
+++ b/src/corelib/time/qdatetimeparser.cpp
@@ -13,6 +13,9 @@
#include "qtimezone.h"
#include "qvarlengtharray.h"
#include "private/qlocale_p.h"
+#if QT_CONFIG(timezone)
+#include "private/qtimezoneprivate_p.h"
+#endif
#include "private/qstringiterator_p.h"
#include "private/qtenvironmentvariables_p.h"
@@ -1228,6 +1231,27 @@ static int startsWithLocalTimeZone(QStringView name, const QDateTime &when, cons
return int(longest);
}
+#if QT_CONFIG(timezone)
+static auto findZoneByLongName(QStringView str, const QLocale &locale, const QDateTime &when)
+{
+ struct R
+ {
+ QTimeZone zone;
+ qsizetype nameLength = 0;
+ bool isValid() const { return nameLength > 0 && zone.isValid(); }
+ } result;
+ auto pfx = QTimeZonePrivate::findLongNamePrefix(str, locale, when.toMSecsSinceEpoch());
+ if (!pfx.nameLength) // Incomplete data in when: try without time-point.
+ pfx = QTimeZonePrivate::findLongNamePrefix(str, locale);
+ if (pfx.nameLength > 0) {
+ result = R{ QTimeZone(pfx.ianaId), pfx.nameLength };
+ Q_ASSERT(result.zone.isValid());
+ // TODO: we should be able to take pfx.timeType into account.
+ }
+ return result;
+}
+#endif // timezone
+
/*!
\internal
*/
@@ -1313,9 +1337,14 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, bool fixup) const
timeZone = QTimeZone::fromSecondsAheadOfUtc(sect.value);
#if QT_CONFIG(timezone)
} else if (startsWithLocalTimeZone(zoneName, usedDateTime, locale()) != sect.used) {
- QTimeZone namedZone = QTimeZone(zoneName.toLatin1());
- Q_ASSERT(namedZone.isValid());
- timeZone = namedZone;
+ if (QTimeZone namedZone = QTimeZone(zoneName.toLatin1()); namedZone.isValid()) {
+ timeZone = namedZone;
+ } else {
+ auto found = findZoneByLongName(zoneName, locale(), usedDateTime);
+ Q_ASSERT(found.isValid());
+ Q_ASSERT(found.nameLength == zoneName.length());
+ timeZone = found.zone;
+ }
#endif
} else {
timeZone = QTimeZone::LocalTime;
@@ -1853,12 +1882,17 @@ QDateTimeParser::findTimeZoneName(QStringView str, const QDateTime &when) const
lastSlash = slash;
}
- for (; index > systemLength; --index) { // Find longest match
- str.truncate(index);
- QTimeZone zone(str.toLatin1());
+ // Find longest IANA ID match:
+ for (QStringView copy = str; index > systemLength; --index) {
+ copy.truncate(index);
+ QTimeZone zone(copy.toLatin1());
if (zone.isValid())
return ParsedSection(Acceptable, zone.offsetFromUtc(when), index);
}
+ // Not a known IANA ID.
+
+ if (auto found = findZoneByLongName(str, locale(), when); found.isValid())
+ return ParsedSection(Acceptable, found.zone.offsetFromUtc(when), found.nameLength);
#endif
if (systemLength > 0) // won't actually use the offset, but need it to be valid
return ParsedSection(Acceptable, when.toLocalTime().offsetFromUtc(), systemLength);
close