From 9e01a9a5d174a274091cef011e55a18ee3460cdc Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 23 Mar 2022 14:23:34 +0100 Subject: [PATCH] Apply the East-Saskatchewan exception to zone-fragment lengths to ICU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The exception was previously limited to Android, but I now find that ICU has the same over-long names; it seems likely that's where Android gets them. Also update the link to the theory page from the TZ DB, as it now has an official home on www.iana.org. Task-number: QTBUG-99747 Pick-to: 6.3 6.2 Change-Id: I9af67426d15609dfaf5f335405ceb1218fcf40ff Reviewed-by: MÃ¥rten Nordheim --- src/corelib/time/qtimezoneprivate.cpp | 14 +++++++++----- .../auto/corelib/time/qtimezone/tst_qtimezone.cpp | 4 ++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp index e3f392230a9..d1f63305599 100644 --- a/src/corelib/time/qtimezoneprivate.cpp +++ b/src/corelib/time/qtimezoneprivate.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Copyright (C) 2013 John Layt ** Contact: https://www.qt.io/licensing/ ** @@ -582,16 +582,20 @@ QTimeZone::OffsetData QTimeZonePrivate::toOffsetData(const QTimeZonePrivate::Dat bool QTimeZonePrivate::isValidId(const QByteArray &ianaId) { /* - Main rules for defining TZ/IANA names as per ftp://ftp.iana.org/tz/code/Theory + Main rules for defining TZ/IANA names, as per + https://www.iana.org/time-zones/repository/theory.html, are: 1. Use only valid POSIX file name components 2. Within a file name component, use only ASCII letters, `.', `-' and `_'. 3. Do not use digits (except in a [+-]\d+ suffix, when used). 4. A file name component must not exceed 14 characters or start with `-' + However, the rules are really guidelines - a later one says - Do not change established names if they only marginally violate the above rules. We may, therefore, need to be a bit slack in our check here, if we hit - legitimate exceptions in real time-zone databases. + legitimate exceptions in real time-zone databases. In particular, ICU + includes some non-standard names with some components > 14 characters + long; so does Android, possibly deriving them from ICU. In particular, aliases such as "Etc/GMT+7" and "SystemV/EST5EDT" are valid so we need to accept digits, ':', and '+'; aliases typically have the form @@ -618,8 +622,8 @@ bool QTimeZonePrivate::isValidId(const QByteArray &ianaId) // Somewhat slack hand-rolled version: const int MinSectionLength = 1; -#ifdef Q_OS_ANDROID - // Android has its own naming of zones. +#if defined(Q_OS_ANDROID) || QT_CONFIG(icu) + // Android has its own naming of zones. It may well come from ICU. // "Canada/East-Saskatchewan" has a 17-character second component. const int MaxSectionLength = 17; #else diff --git a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp index 13ccd4dfb2c..7db2b980593 100644 --- a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp +++ b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp @@ -865,7 +865,7 @@ void tst_QTimeZone::isValidId_data() // Parts separated by '/', each part min 1 and max of 14 chars TESTSET("empty", "", false); TESTSET("minimal", "m", true); -#ifdef Q_OS_ANDROID +#if defined(Q_OS_ANDROID) || QT_CONFIG(icu) TESTSET("maximal", "East-Saskatchewan", true); // Android actually uses this TESTSET("too long", "North-Saskatchewan", false); // ... but thankfully not this. #else @@ -936,7 +936,7 @@ void tst_QTimeZone::isValidId_data() QTest::newRow("a,z alone") << QByteArray("a,z") << false; QTest::newRow("/z alone") << QByteArray("/z") << false; QTest::newRow("-z alone") << QByteArray("-z") << false; -#ifdef Q_OS_ANDROID +#if defined(Q_OS_ANDROID) || QT_CONFIG(icu) QTest::newRow("long alone") << QByteArray("12345678901234567") << true; QTest::newRow("over-long alone") << QByteArray("123456789012345678") << false; #else