Apply the East-Saskatchewan exception to zone-fragment lengths to ICU

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 <marten.nordheim@qt.io>
This commit is contained in:
Edward Welbourne 2022-03-23 14:23:34 +01:00
parent 460d7c8780
commit 9e01a9a5d1
2 changed files with 11 additions and 7 deletions

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2021 The Qt Company Ltd. ** Copyright (C) 2022 The Qt Company Ltd.
** Copyright (C) 2013 John Layt <jlayt@kde.org> ** Copyright (C) 2013 John Layt <jlayt@kde.org>
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
@ -582,16 +582,20 @@ QTimeZone::OffsetData QTimeZonePrivate::toOffsetData(const QTimeZonePrivate::Dat
bool QTimeZonePrivate::isValidId(const QByteArray &ianaId) 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 1. Use only valid POSIX file name components
2. Within a file name component, use only ASCII letters, `.', `-' and `_'. 2. Within a file name component, use only ASCII letters, `.', `-' and `_'.
3. Do not use digits (except in a [+-]\d+ suffix, when used). 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 `-' 4. A file name component must not exceed 14 characters or start with `-'
However, the rules are really guidelines - a later one says However, the rules are really guidelines - a later one says
- Do not change established names if they only marginally violate the - Do not change established names if they only marginally violate the
above rules. above rules.
We may, therefore, need to be a bit slack in our check here, if we hit 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 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 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: // Somewhat slack hand-rolled version:
const int MinSectionLength = 1; const int MinSectionLength = 1;
#ifdef Q_OS_ANDROID #if defined(Q_OS_ANDROID) || QT_CONFIG(icu)
// Android has its own naming of zones. // Android has its own naming of zones. It may well come from ICU.
// "Canada/East-Saskatchewan" has a 17-character second component. // "Canada/East-Saskatchewan" has a 17-character second component.
const int MaxSectionLength = 17; const int MaxSectionLength = 17;
#else #else

View File

@ -865,7 +865,7 @@ void tst_QTimeZone::isValidId_data()
// Parts separated by '/', each part min 1 and max of 14 chars // Parts separated by '/', each part min 1 and max of 14 chars
TESTSET("empty", "", false); TESTSET("empty", "", false);
TESTSET("minimal", "m", true); 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("maximal", "East-Saskatchewan", true); // Android actually uses this
TESTSET("too long", "North-Saskatchewan", false); // ... but thankfully not this. TESTSET("too long", "North-Saskatchewan", false); // ... but thankfully not this.
#else #else
@ -936,7 +936,7 @@ void tst_QTimeZone::isValidId_data()
QTest::newRow("a,z alone") << QByteArray("a,z") << false; QTest::newRow("a,z alone") << QByteArray("a,z") << false;
QTest::newRow("/z alone") << QByteArray("/z") << false; QTest::newRow("/z alone") << QByteArray("/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("long alone") << QByteArray("12345678901234567") << true;
QTest::newRow("over-long alone") << QByteArray("123456789012345678") << false; QTest::newRow("over-long alone") << QByteArray("123456789012345678") << false;
#else #else