From 38b8c153584037ed6e7e49023c28d4590de176bc Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 7 Oct 2024 17:14:53 +0200 Subject: [PATCH] Cope with empty name for a time zone QTimeZone::displayName() may return empty if it has no suitably-localized name for the zone. So QCalendarBackend's dateTimeToString() can't rely on its tzAbbr() returning a string that starts with UTC (and it may now, with proper L10n, start with some other prefix) or indeed has length >= 3 (so sliced(3) could crash). Rework the handling of offset name (mainly for the pick back to 6.8, as I'll be back to get rid of the kludging in 6.9) to at least not crash on empty return. In the process, use decreasingly appropriate forms as fallbacks if we don't get what we want. Fixes: QTBUG-129696 Change-Id: Id4f42778ca9a4806ac5dba23ce7068261a90500b Reviewed-by: Thiago Macieira (cherry picked from commit 9e749df879a5bc76fa416c96f73378d81608801f) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/text/qlocale.cpp | 38 ++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp index 9b1b6d73b9f..1408de33f11 100644 --- a/src/corelib/text/qlocale.cpp +++ b/src/corelib/text/qlocale.cpp @@ -3705,11 +3705,18 @@ QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime & QTimeZone::NameType mode = type == Short ? QTimeZone::ShortName : type == Long ? QTimeZone::LongName : QTimeZone::OffsetName; - return when.timeRepresentation().displayName(when, mode, locale); + QString text = when.timeRepresentation().displayName(when, mode, locale); + if (!text.isEmpty()) + return text; + // else fall back to an unlocalized one if we can manage it: } // else: prefer QDateTime's abbreviation, for backwards-compatibility. #endif // else, make do with non-localized abbreviation: - if (type != Offset) - return when.timeZoneAbbreviation(); + if (type != Offset) { + QString text = when.timeZoneAbbreviation(); + if (!text.isEmpty()) + return text; + // else fall back to Offset version: + } // For Offset, we can coerce to a UTC-based zone's abbreviation: return when.toOffsetFromUtc(when.offsetFromUtc()).timeZoneAbbreviation(); }; @@ -3725,16 +3732,21 @@ QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime & case 3: // ±hh:mm case 2: // ±hhmm (we'll remove the ':' at the end) text = tzAbbr(when, Offset); - Q_ASSERT(text.startsWith("UTC"_L1)); // Need to strip this. - // The Qt::UTC case omits the zero offset: - text = (text.size() == 3 - ? u"+00:00"_s - : (text.size() <= 6 - // Whole-hour offsets may lack the zero minutes: - ? QStringView{text}.sliced(3) + ":00"_L1 - : std::move(text).sliced(3))); - if (repeat == 2) - text = text.remove(u':'); + if (!text.isEmpty()) { + QStringView tail{text}; + // May need to strip a prefix: + if (tail.startsWith("UTC"_L1) || tail.startsWith("GMT"_L1)) + tail = tail.sliced(3); + // TODO: there may be a locale-specific alternative prefix. + text = (tail.isEmpty() // The Qt::UTC case omits the zero offset: + ? u"+00:00"_s + // Whole-hour offsets may lack the zero minutes: + : (tail.size() <= 3 + ? tail + ":00"_L1 + : std::move(text).right(tail.size()))); + if (repeat == 2) + text.remove(u':'); + } // else: no suitable representation of the zone. break; default: text = tzAbbr(when, Short);