Use CLDR alias data to find canonical IANA IDs

There are various legacy IANA IDs that we should recognize as aliases
for their contemporary equivalents. Later work shall also take these
into account in the Windows IDs. Scan CLDR's data about these aliases
and use it when constructing QTimeZone. This adds aliasMappingTable
and aliasIdData arrays to QTZP_data_p.h and an AliasData type to its
QtTimeZoneCldr namespace.

Change-Id: I1bbfce62959a7e1b7a0bc4a320c32f5a174a2ff2
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Edward Welbourne 2024-02-06 11:52:47 +01:00
parent 421b05331c
commit bcadcb029e
6 changed files with 474 additions and 15 deletions

View File

@ -455,10 +455,17 @@ QTimeZone::QTimeZone(const QByteArray &ianaId)
d = new QUtcTimeZonePrivate(ianaId);
// If not recognized, try creating it with the system backend.
if (!d->isValid()) {
if (ianaId.isEmpty())
if (ianaId.isEmpty()) {
d = newBackendTimeZone();
else // Constructor MUST produce invalid for unsupported ID.
} else { // Constructor MUST produce invalid for unsupported ID.
d = newBackendTimeZone(ianaId);
if (!d->isValid()) {
// We may have a legacy alias for a supported IANA ID:
const QByteArray name = QTimeZonePrivate::aliasToIana(ianaId);
if (!name.isEmpty() && name != ianaId)
d = newBackendTimeZone(name);
}
}
}
// Can also handle UTC with arbitrary (valid) offset, but only do so as
// fall-back, since either of the above may handle it more informatively.

View File

@ -54,6 +54,11 @@ constexpr bool atLowerWindowsKey(const WindowsData &entry, qint16 winIdKey) noex
return entry.windowsIdKey < winIdKey;
}
static bool earlierAliasId(const AliasData &entry, QByteArrayView aliasId) noexcept
{
return entry.aliasId().compare(aliasId, Qt::CaseInsensitive) < 0;
}
static bool earlierWindowsId(const WindowsData &entry, QByteArrayView winId) noexcept
{
return entry.windowsId().compare(winId, Qt::CaseInsensitive) < 0;
@ -769,6 +774,15 @@ QString QTimeZonePrivate::isoOffsetFormat(int offsetFromUtc, QTimeZone::NameType
return result;
}
QByteArray QTimeZonePrivate::aliasToIana(QByteArrayView alias)
{
const auto data = std::lower_bound(std::begin(aliasMappingTable), std::end(aliasMappingTable),
alias, earlierAliasId);
if (data != std::end(aliasMappingTable) && data->aliasId() == alias)
return data->ianaId().toByteArray();
return {};
}
QByteArray QTimeZonePrivate::ianaIdToWindowsId(const QByteArray &id)
{
const auto idUtf8 = QUtf8StringView(id);

View File

@ -25,7 +25,7 @@ QT_BEGIN_NAMESPACE
namespace QtTimeZoneCldr {
/*
Recognized UTC-offset zones and CLDR-derived data on Windows IDs.
Recognized UTC-offset zones and CLDR-derived data on timezone IDs.
The UTC-offset zone table is provided for generic UTC±HH:mm format time
zones. The UTC backend can support arbitrary offsets in seconds, but only
@ -44,6 +44,17 @@ namespace QtTimeZoneCldr {
of its last update and how to update it.
*/
struct AliasData
{
// Table is sorted on aliasId(), then on ianaId().
// Indices in alias table, not IANA (group) table
quint16 aliasIdIndex;
quint16 ianaIdIndex;
// Values for the actual IDs:
constexpr QByteArrayView aliasId() const;
constexpr QByteArrayView ianaId() const;
};
struct ZoneData
{
// Keys (table is sorted in Windows ID, then on territory enum value):
@ -77,8 +88,8 @@ struct UtcData
// GENERATED PART STARTS HERE
/*
This part of the file was generated on 2024-01-29 from the
Common Locale Data Repository v43 file supplemental/windowsZones.xml
This part of the file was generated on 2024-02-06 from the
Common Locale Data Repository v43
http://www.unicode.org/cldr/
@ -86,6 +97,144 @@ struct UtcData
edited) CLDR data; see qtbase/util/locale_database/.
*/
// Alias ID Index, IANA ID Index
static constexpr AliasData aliasMappingTable[] = {
{ 0, 14 }, // Africa/Asmara -> Africa/Asmera
{ 28, 44 }, // Africa/Timbuktu -> Africa/Bamako
{ 58, 89 }, // America/Argentina/Buenos_Aires -> America/Buenos_Aires
{ 110, 138 }, // America/Argentina/Catamarca -> America/Catamarca
{ 156, 138 }, // America/Argentina/ComodRivadavia -> America/Catamarca
{ 189, 215 }, // America/Argentina/Cordoba -> America/Cordoba
{ 231, 255 }, // America/Argentina/Jujuy -> America/Jujuy
{ 269, 295 }, // America/Argentina/Mendoza -> America/Mendoza
{ 311, 328 }, // America/Atikokan -> America/Coral_Harbour
{ 350, 363 }, // America/Atka -> America/Adak
{ 376, 393 }, // America/Ensenada -> America/Tijuana
{ 409, 428 }, // America/Fort_Wayne -> America/Indianapolis
{ 449, 428 }, // America/Indiana/Indianapolis -> America/Indianapolis
{ 478, 506 }, // America/Kentucky/Louisville -> America/Louisville
{ 525, 541 }, // America/Knox_IN -> America/Indiana/Knox
{ 562, 579 }, // America/Montreal -> America/Toronto
{ 595, 608 }, // America/Nuuk -> America/Godthab
{ 624, 643 }, // America/Porto_Acre -> America/Rio_Branco
{ 662, 215 }, // America/Rosario -> America/Cordoba
{ 678, 695 }, // America/Shiprock -> America/Denver
{ 710, 725 }, // America/Virgin -> America/St_Thomas
{ 743, 765 }, // Antarctica/South_Pole -> Pacific/Auckland
{ 782, 797 }, // Asia/Ashkhabad -> Asia/Ashgabat
{ 811, 826 }, // Asia/Chongqing -> Asia/Shanghai
{ 840, 826 }, // Asia/Chungking -> Asia/Shanghai
{ 855, 866 }, // Asia/Dacca -> Asia/Dhaka
{ 877, 826 }, // Asia/Harbin -> Asia/Shanghai
{ 889, 906 }, // Asia/Ho_Chi_Minh -> Asia/Saigon
{ 918, 932 }, // Asia/Istanbul -> Europe/Istanbul
{ 948, 961 }, // Asia/Kashgar -> Asia/Urumqi
{ 973, 988 }, // Asia/Kathmandu -> Asia/Katmandu
{ 1002, 1015 }, // Asia/Kolkata -> Asia/Calcutta
{ 1029, 1040 }, // Asia/Macao -> Asia/Macau
{ 1051, 1065 }, // Asia/Tel_Aviv -> Asia/Jerusalem
{ 1080, 1092 }, // Asia/Thimbu -> Asia/Thimphu
{ 1105, 1124 }, // Asia/Ujung_Pandang -> Asia/Makassar
{ 1138, 1154 }, // Asia/Ulan_Bator -> Asia/Ulaanbaatar
{ 1171, 1183 }, // Asia/Yangon -> Asia/Rangoon
{ 1196, 1211 }, // Atlantic/Faroe -> Atlantic/Faeroe
{ 1227, 1246 }, // Atlantic/Jan_Mayen -> Arctic/Longyearbyen
{ 1266, 1280 }, // Australia/ACT -> Australia/Sydney
{ 1297, 1280 }, // Australia/Canberra -> Australia/Sydney
{ 1316, 1330 }, // Australia/LHI -> Australia/Lord_Howe
{ 1350, 1280 }, // Australia/NSW -> Australia/Sydney
{ 1364, 1380 }, // Australia/North -> Australia/Darwin
{ 1397, 1418 }, // Australia/Queensland -> Australia/Brisbane
{ 1437, 1453 }, // Australia/South -> Australia/Adelaide
{ 1472, 1491 }, // Australia/Tasmania -> Australia/Hobart
{ 1508, 1527 }, // Australia/Victoria -> Australia/Melbourne
{ 1547, 1562 }, // Australia/West -> Australia/Perth
{ 1578, 1599 }, // Australia/Yancowinna -> Australia/Broken_Hill
{ 1621, 643 }, // Brazil/Acre -> America/Rio_Branco
{ 1633, 1650 }, // Brazil/DeNoronha -> America/Noronha
{ 1666, 1678 }, // Brazil/East -> America/Sao_Paulo
{ 1696, 1708 }, // Brazil/West -> America/Manaus
{ 1723, 1739 }, // Canada/Atlantic -> America/Halifax
{ 1755, 1770 }, // Canada/Central -> America/Winnipeg
{ 1787, 1812 }, // Canada/East-Saskatchewan -> America/Regina
{ 1827, 579 }, // Canada/Eastern -> America/Toronto
{ 1842, 1858 }, // Canada/Mountain -> America/Edmonton
{ 1875, 1895 }, // Canada/Newfoundland -> America/St_Johns
{ 1912, 1927 }, // Canada/Pacific -> America/Vancouver
{ 1945, 1812 }, // Canada/Saskatchewan -> America/Regina
{ 1965, 1978 }, // Canada/Yukon -> America/Whitehorse
{ 1997, 2015 }, // Chile/Continental -> America/Santiago
{ 2032, 2051 }, // Chile/EasterIsland -> Pacific/Easter
{ 2066, 2071 }, // Cuba -> America/Havana
{ 2086, 2090 }, // EST -> Etc/GMT+5
{ 2100, 2106 }, // Egypt -> Africa/Cairo
{ 2119, 2124 }, // Eire -> Europe/Dublin
{ 2138, 2148 }, // Etc/GMT+0 -> Etc/GMT
{ 2156, 2148 }, // Etc/GMT-0 -> Etc/GMT
{ 2166, 2148 }, // Etc/GMT0 -> Etc/GMT
{ 2175, 2148 }, // Etc/Greenwich -> Etc/GMT
{ 2189, 2197 }, // Etc/UCT -> Etc/UTC
{ 2205, 2197 }, // Etc/Universal -> Etc/UTC
{ 2219, 2197 }, // Etc/Zulu -> Etc/UTC
{ 2228, 2243 }, // Europe/Belfast -> Europe/London
{ 2257, 2269 }, // Europe/Kyiv -> Europe/Kiev
{ 2281, 2296 }, // Europe/Nicosia -> Asia/Nicosia
{ 2309, 2325 }, // Europe/Tiraspol -> Europe/Chisinau
{ 2341, 2243 }, // GB -> Europe/London
{ 2344, 2243 }, // GB-Eire -> Europe/London
{ 2352, 2148 }, // GMT -> Etc/GMT
{ 2356, 2148 }, // GMT+0 -> Etc/GMT
{ 2362, 2148 }, // GMT-0 -> Etc/GMT
{ 2368, 2148 }, // GMT0 -> Etc/GMT
{ 2373, 2148 }, // Greenwich -> Etc/GMT
{ 2383, 2387 }, // HST -> Etc/GMT+10
{ 2398, 2407 }, // Hongkong -> Asia/Hong_Kong
{ 2422, 2430 }, // Iceland -> Atlantic/Reykjavik
{ 2449, 2454 }, // Iran -> Asia/Tehran
{ 2466, 1065 }, // Israel -> Asia/Jerusalem
{ 2473, 2481 }, // Jamaica -> America/Jamaica
{ 2497, 2503 }, // Japan -> Asia/Tokyo
{ 2514, 2524 }, // Kwajalein -> Pacific/Kwajalein
{ 2542, 2548 }, // Libya -> Africa/Tripoli
{ 2563, 2567 }, // MST -> Etc/GMT+7
{ 2577, 393 }, // Mexico/BajaNorte -> America/Tijuana
{ 2594, 2609 }, // Mexico/BajaSur -> America/Mazatlan
{ 2626, 2641 }, // Mexico/General -> America/Mexico_City
{ 2661, 765 }, // NZ -> Pacific/Auckland
{ 2664, 2672 }, // NZ-CHAT -> Pacific/Chatham
{ 2688, 695 }, // Navajo -> America/Denver
{ 2695, 826 }, // PRC -> Asia/Shanghai
{ 2699, 2713 }, // Pacific/Chuuk -> Pacific/Truk
{ 2726, 2741 }, // Pacific/Kanton -> Pacific/Enderbury
{ 2759, 2775 }, // Pacific/Pohnpei -> Pacific/Ponape
{ 2790, 2804 }, // Pacific/Samoa -> Pacific/Pago_Pago
{ 2822, 2713 }, // Pacific/Yap -> Pacific/Truk
{ 2834, 2841 }, // Poland -> Europe/Warsaw
{ 2855, 2864 }, // Portugal -> Europe/Lisbon
{ 2878, 2882 }, // ROC -> Asia/Taipei
{ 2894, 2898 }, // ROK -> Asia/Seoul
{ 2909, 2919 }, // Singapore -> Asia/Singapore
{ 2934, 932 }, // Turkey -> Europe/Istanbul
{ 2941, 2197 }, // UCT -> Etc/UTC
{ 2945, 2955 }, // US/Alaska -> America/Anchorage
{ 2973, 363 }, // US/Aleutian -> America/Adak
{ 2985, 2996 }, // US/Arizona -> America/Phoenix
{ 3012, 3023 }, // US/Central -> America/Chicago
{ 3039, 428 }, // US/East-Indiana -> America/Indianapolis
{ 3055, 3066 }, // US/Eastern -> America/New_York
{ 3083, 3093 }, // US/Hawaii -> Pacific/Honolulu
{ 3110, 541 }, // US/Indiana-Starke -> America/Indiana/Knox
{ 3128, 3140 }, // US/Michigan -> America/Detroit
{ 3156, 695 }, // US/Mountain -> America/Denver
{ 3168, 3179 }, // US/Pacific -> America/Los_Angeles
{ 3199, 3179 }, // US/Pacific-New -> America/Los_Angeles
{ 3214, 2804 }, // US/Samoa -> Pacific/Pago_Pago
{ 3223, 2197 }, // UTC -> Etc/UTC
{ 3227, 2197 }, // Universal -> Etc/UTC
{ 3237, 3242 }, // W-SU -> Europe/Moscow
{ 3256, 2197 }, // Zulu -> Etc/UTC
};
// Windows ID Key, Territory Enum, IANA ID Index
static constexpr ZoneData zoneDataTable[] = {
{ 1, 1, 0 }, // Afghanistan Standard Time / Afghanistan
@ -1361,8 +1510,217 @@ static constexpr char ianaIdData[] = {
0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b,
0x31, 0x34, 0x3a, 0x30, 0x30, 0x0
};
static constexpr char aliasIdData[] = {
0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x6d, 0x61, 0x72, 0x61, 0x0, 0x41, 0x66,
0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x6d, 0x65, 0x72, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69,
0x63, 0x61, 0x2f, 0x54, 0x69, 0x6d, 0x62, 0x75, 0x6b, 0x74, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69,
0x63, 0x61, 0x2f, 0x42, 0x61, 0x6d, 0x61, 0x6b, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e,
0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x0, 0x41, 0x6d,
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f,
0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
0x61, 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72,
0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x43, 0x6f,
0x6d, 0x6f, 0x64, 0x52, 0x69, 0x76, 0x61, 0x64, 0x61, 0x76, 0x69, 0x61, 0x0, 0x41, 0x6d, 0x65,
0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x43,
0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43,
0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x0, 0x41,
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x0, 0x41, 0x6d, 0x65,
0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4d,
0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d,
0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
0x74, 0x69, 0x6b, 0x6f, 0x6b, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
0x43, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x48, 0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0, 0x41, 0x6d,
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x74, 0x6b, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
0x63, 0x61, 0x2f, 0x41, 0x64, 0x61, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
0x45, 0x6e, 0x73, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x57, 0x61, 0x79, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72,
0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73,
0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61,
0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x0, 0x41, 0x6d,
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e, 0x74, 0x75, 0x63, 0x6b, 0x79, 0x2f, 0x4c,
0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65,
0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x5f, 0x49, 0x4e, 0x0, 0x41, 0x6d, 0x65,
0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f,
0x78, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65,
0x61, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, 0x6f, 0x6e,
0x74, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x75, 0x75, 0x6b, 0x0,
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x64, 0x74, 0x68, 0x61, 0x62, 0x0,
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x41, 0x63,
0x72, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x42,
0x72, 0x61, 0x6e, 0x63, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x6f,
0x73, 0x61, 0x72, 0x69, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x68,
0x69, 0x70, 0x72, 0x6f, 0x63, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44,
0x65, 0x6e, 0x76, 0x65, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x69,
0x72, 0x67, 0x69, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f,
0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63,
0x61, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x5f, 0x50, 0x6f, 0x6c, 0x65, 0x0, 0x50, 0x61, 0x63,
0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x73,
0x69, 0x61, 0x2f, 0x41, 0x73, 0x68, 0x6b, 0x68, 0x61, 0x62, 0x61, 0x64, 0x0, 0x41, 0x73, 0x69,
0x61, 0x2f, 0x41, 0x73, 0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
0x43, 0x68, 0x6f, 0x6e, 0x67, 0x71, 0x69, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53,
0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x75,
0x6e, 0x67, 0x6b, 0x69, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x63, 0x63,
0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0, 0x41, 0x73, 0x69,
0x61, 0x2f, 0x48, 0x61, 0x72, 0x62, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f,
0x5f, 0x43, 0x68, 0x69, 0x5f, 0x4d, 0x69, 0x6e, 0x68, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53,
0x61, 0x69, 0x67, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x73, 0x74, 0x61, 0x6e,
0x62, 0x75, 0x6c, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74, 0x61, 0x6e,
0x62, 0x75, 0x6c, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x73, 0x68, 0x67, 0x61, 0x72,
0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75, 0x6d, 0x71, 0x69, 0x0, 0x41, 0x73, 0x69,
0x61, 0x2f, 0x4b, 0x61, 0x74, 0x68, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0, 0x41, 0x73, 0x69, 0x61,
0x2f, 0x4b, 0x61, 0x74, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b,
0x6f, 0x6c, 0x6b, 0x61, 0x74, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63,
0x75, 0x74, 0x74, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x6f, 0x0,
0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
0x54, 0x65, 0x6c, 0x5f, 0x41, 0x76, 0x69, 0x76, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65,
0x72, 0x75, 0x73, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69,
0x6d, 0x62, 0x75, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69, 0x6d, 0x70, 0x68, 0x75,
0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6a, 0x75, 0x6e, 0x67, 0x5f, 0x50, 0x61, 0x6e, 0x64,
0x61, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73, 0x73, 0x61,
0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x6e, 0x5f, 0x42, 0x61, 0x74, 0x6f,
0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74,
0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6e, 0x67, 0x6f, 0x6e, 0x0, 0x41,
0x73, 0x69, 0x61, 0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0, 0x41, 0x74, 0x6c, 0x61,
0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46, 0x61, 0x72, 0x6f, 0x65, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e,
0x74, 0x69, 0x63, 0x2f, 0x46, 0x61, 0x65, 0x72, 0x6f, 0x65, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e,
0x74, 0x69, 0x63, 0x2f, 0x4a, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x79, 0x65, 0x6e, 0x0, 0x41, 0x72,
0x63, 0x74, 0x69, 0x63, 0x2f, 0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65,
0x6e, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x43, 0x54, 0x0,
0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79,
0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6e, 0x62, 0x65,
0x72, 0x72, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x48,
0x49, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x6f, 0x72, 0x64,
0x5f, 0x48, 0x6f, 0x77, 0x65, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
0x4e, 0x53, 0x57, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4e, 0x6f,
0x72, 0x74, 0x68, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x44, 0x61,
0x72, 0x77, 0x69, 0x6e, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x51,
0x75, 0x65, 0x65, 0x6e, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61,
0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x75, 0x73,
0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x0, 0x41, 0x75, 0x73,
0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, 0x0,
0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x6d, 0x61, 0x6e,
0x69, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x62,
0x61, 0x72, 0x74, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x56, 0x69,
0x63, 0x74, 0x6f, 0x72, 0x69, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
0x2f, 0x4d, 0x65, 0x6c, 0x62, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72,
0x61, 0x6c, 0x69, 0x61, 0x2f, 0x57, 0x65, 0x73, 0x74, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61,
0x6c, 0x69, 0x61, 0x2f, 0x50, 0x65, 0x72, 0x74, 0x68, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61,
0x6c, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6e, 0x63, 0x6f, 0x77, 0x69, 0x6e, 0x6e, 0x61, 0x0, 0x41,
0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x5f,
0x48, 0x69, 0x6c, 0x6c, 0x0, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x2f, 0x41, 0x63, 0x72, 0x65,
0x0, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x2f, 0x44, 0x65, 0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68,
0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68,
0x61, 0x0, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x0, 0x41, 0x6d,
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0,
0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x2f, 0x57, 0x65, 0x73, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72,
0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64,
0x61, 0x2f, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64,
0x61, 0x2f, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
0x61, 0x2f, 0x57, 0x69, 0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64,
0x61, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x2d, 0x53, 0x61, 0x73, 0x6b, 0x61, 0x74, 0x63, 0x68, 0x65,
0x77, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x67, 0x69,
0x6e, 0x61, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72,
0x6e, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69,
0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74,
0x6f, 0x6e, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x66, 0x6f, 0x75,
0x6e, 0x64, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53,
0x74, 0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x50,
0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56,
0x61, 0x6e, 0x63, 0x6f, 0x75, 0x76, 0x65, 0x72, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f,
0x53, 0x61, 0x73, 0x6b, 0x61, 0x74, 0x63, 0x68, 0x65, 0x77, 0x61, 0x6e, 0x0, 0x43, 0x61, 0x6e,
0x61, 0x64, 0x61, 0x2f, 0x59, 0x75, 0x6b, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
0x61, 0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0, 0x43, 0x68, 0x69,
0x6c, 0x65, 0x2f, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x0, 0x41,
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x67, 0x6f, 0x0,
0x43, 0x68, 0x69, 0x6c, 0x65, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x49, 0x73, 0x6c, 0x61,
0x6e, 0x64, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65,
0x72, 0x0, 0x43, 0x75, 0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48,
0x61, 0x76, 0x61, 0x6e, 0x61, 0x0, 0x45, 0x53, 0x54, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
0x54, 0x2b, 0x35, 0x0, 0x45, 0x67, 0x79, 0x70, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0, 0x45, 0x69, 0x72, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f,
0x70, 0x65, 0x2f, 0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
0x54, 0x2b, 0x30, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0, 0x45, 0x74, 0x63, 0x2f,
0x47, 0x4d, 0x54, 0x2d, 0x30, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x30, 0x0, 0x45,
0x74, 0x63, 0x2f, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68, 0x0, 0x45, 0x74, 0x63,
0x2f, 0x55, 0x43, 0x54, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x55, 0x54, 0x43, 0x0, 0x45, 0x74, 0x63,
0x2f, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x5a,
0x75, 0x6c, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x66, 0x61,
0x73, 0x74, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e,
0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x79, 0x69, 0x76, 0x0, 0x45, 0x75, 0x72,
0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
0x4e, 0x69, 0x63, 0x6f, 0x73, 0x69, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63,
0x6f, 0x73, 0x69, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x69, 0x72, 0x61,
0x73, 0x70, 0x6f, 0x6c, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x68, 0x69, 0x73,
0x69, 0x6e, 0x61, 0x75, 0x0, 0x47, 0x42, 0x0, 0x47, 0x42, 0x2d, 0x45, 0x69, 0x72, 0x65, 0x0,
0x47, 0x4d, 0x54, 0x0, 0x47, 0x4d, 0x54, 0x2b, 0x30, 0x0, 0x47, 0x4d, 0x54, 0x2d, 0x30, 0x0,
0x47, 0x4d, 0x54, 0x30, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68, 0x0, 0x48,
0x53, 0x54, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0, 0x48, 0x6f,
0x6e, 0x67, 0x6b, 0x6f, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x6e, 0x67,
0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0, 0x49, 0x63, 0x65, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x74,
0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b,
0x0, 0x49, 0x72, 0x61, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x65, 0x68, 0x72, 0x61,
0x6e, 0x0, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x0, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61,
0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61,
0x0, 0x4a, 0x61, 0x70, 0x61, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6b, 0x79,
0x6f, 0x0, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69,
0x66, 0x69, 0x63, 0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69, 0x6e, 0x0, 0x4c, 0x69,
0x62, 0x79, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f,
0x6c, 0x69, 0x0, 0x4d, 0x53, 0x54, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x37,
0x0, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x42, 0x61, 0x6a, 0x61, 0x4e, 0x6f, 0x72, 0x74,
0x65, 0x0, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x42, 0x61, 0x6a, 0x61, 0x53, 0x75, 0x72,
0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74, 0x6c, 0x61,
0x6e, 0x0, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f,
0x43, 0x69, 0x74, 0x79, 0x0, 0x4e, 0x5a, 0x0, 0x4e, 0x5a, 0x2d, 0x43, 0x48, 0x41, 0x54, 0x0,
0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x43, 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x0,
0x4e, 0x61, 0x76, 0x61, 0x6a, 0x6f, 0x0, 0x50, 0x52, 0x43, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
0x69, 0x63, 0x2f, 0x43, 0x68, 0x75, 0x75, 0x6b, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
0x2f, 0x54, 0x72, 0x75, 0x6b, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x61,
0x6e, 0x74, 0x6f, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e, 0x64,
0x65, 0x72, 0x62, 0x75, 0x72, 0x79, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50,
0x6f, 0x68, 0x6e, 0x70, 0x65, 0x69, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50,
0x6f, 0x6e, 0x61, 0x70, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x53, 0x61,
0x6d, 0x6f, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f,
0x5f, 0x50, 0x61, 0x67, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x59, 0x61,
0x70, 0x0, 0x50, 0x6f, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
0x57, 0x61, 0x72, 0x73, 0x61, 0x77, 0x0, 0x50, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x61, 0x6c, 0x0,
0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73, 0x62, 0x6f, 0x6e, 0x0, 0x52, 0x4f,
0x43, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x0, 0x52, 0x4f,
0x4b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f, 0x75, 0x6c, 0x0, 0x53, 0x69, 0x6e,
0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67,
0x61, 0x70, 0x6f, 0x72, 0x65, 0x0, 0x54, 0x75, 0x72, 0x6b, 0x65, 0x79, 0x0, 0x55, 0x43, 0x54,
0x0, 0x55, 0x53, 0x2f, 0x41, 0x6c, 0x61, 0x73, 0x6b, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x0, 0x55, 0x53, 0x2f,
0x41, 0x6c, 0x65, 0x75, 0x74, 0x69, 0x61, 0x6e, 0x0, 0x55, 0x53, 0x2f, 0x41, 0x72, 0x69, 0x7a,
0x6f, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65,
0x6e, 0x69, 0x78, 0x0, 0x55, 0x53, 0x2f, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x0, 0x41,
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0, 0x55,
0x53, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x2d, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x0, 0x55,
0x53, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f, 0x72, 0x6b, 0x0, 0x55, 0x53, 0x2f, 0x48, 0x61,
0x77, 0x61, 0x69, 0x69, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e,
0x6f, 0x6c, 0x75, 0x6c, 0x75, 0x0, 0x55, 0x53, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61,
0x2d, 0x53, 0x74, 0x61, 0x72, 0x6b, 0x65, 0x0, 0x55, 0x53, 0x2f, 0x4d, 0x69, 0x63, 0x68, 0x69,
0x67, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x74, 0x72,
0x6f, 0x69, 0x74, 0x0, 0x55, 0x53, 0x2f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x0,
0x55, 0x53, 0x2f, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x0, 0x55,
0x53, 0x2f, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2d, 0x4e, 0x65, 0x77, 0x0, 0x55, 0x53,
0x2f, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x6e, 0x69, 0x76, 0x65,
0x72, 0x73, 0x61, 0x6c, 0x0, 0x57, 0x2d, 0x53, 0x55, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0, 0x5a, 0x75, 0x6c, 0x75, 0x0
};
// GENERATED PART ENDS HERE
constexpr QByteArrayView AliasData::aliasId() const { return aliasIdData + aliasIdIndex; }
constexpr QByteArrayView AliasData::ianaId() const { return aliasIdData + ianaIdIndex; }
constexpr QByteArrayView WindowsData::windowsId() const { return windowsIdData + windowsIdIndex; }
// Each of the following returns a space-joined sequence of IANA IDs:
constexpr QByteArrayView WindowsData::ianaId() const { return ianaIdData + ianaIdIndex; }

View File

@ -133,6 +133,7 @@ public:
static QString isoOffsetFormat(int offsetFromUtc,
QTimeZone::NameType mode = QTimeZone::OffsetName);
static QByteArray aliasToIana(QByteArrayView alias);
static QByteArray ianaIdToWindowsId(const QByteArray &ianaId);
static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId);
static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId,

View File

@ -405,6 +405,59 @@ enumdata.py (keeping the old name as an alias):
+ '\n')
grumble('\n')
def bcp47Aliases(self):
"""Reads the mapping from CLDR IDs to IANA IDs
CLDR identifies timezones in various ways but its standard
'name' for them, here described as a CLDR ID, has the form of
an IANA ID. CLDR IDs are stable across time, where IANA IDs
may be revised over time, for example Asia/Calcutta became
Asia/Kolkata. When a new zone is added to CLDR, it gets the
then-current IANA ID as its CLDR ID; if it is later
superseded, CLDR continues using the old ID, so we need a
mapping from that to current IANA IDs. Helpfully, CLDR
provides information about aliasing among time-zone IDs.
The file common/bcp47/timezone.xml has keyword/key/type
elements with attributes:
name -- zone code (ignore)
description -- long name for exemplar location, including
territory
and some of:
deprecated -- ignore entry if present (has no alias)
preferred -- only present if deprecated
since -- version at which this entry was added (ignore)
alias -- space-joined sequence of IANA-form IDs; first is CLDR ID
iana -- if present, repeats the alias entry that's the modern IANA ID
This returns a pair (alias, naming) wherein: alias is a
mapping from IANA-format IDs to actual IANA IDs, that maps
each alias to the contemporary ID used by IANA; and naming is
a mapping from IANA ID to the description it and its aliases
shared in their keyword/key/type entry."""
# File has the same form as supplements:
root = Supplement(Node(self.__xml('common/bcp47/timezone.xml')))
# If we ever need a mapping back to CLDR ID, we can make
# (description, space-joined-list) the naming values.
alias, naming = {}, {} # { alias: iana }, { iana: description }
for item, attrs in root.find('keyword/key/type', exclude=('deprecated',)):
assert 'description' in attrs, item
assert 'alias' in attrs, item
names = attrs['alias'].split()
assert not any(name in alias for name in names), item
# CLDR ID is names[0]; if IANA now uses another name for
# it, this is given as the iana attribute.
ianaid, fullName = attrs.get('iana', names[0]), attrs['description']
alias.update({name: ianaid for name in names})
assert not ianaid in naming
naming[ianaid] = fullName
return alias, naming
def readWindowsTimeZones(self, lookup): # For use by cldr2qtimezone.py
"""Digest CLDR's MS-Win time-zone name mapping.

View File

@ -48,17 +48,18 @@ class ByteArrayData:
class ZoneIdWriter (SourceFileEditor):
# All the output goes into namespace QtTimeZoneCldr.
def write(self, version, defaults, windowsIds):
def write(self, version, alias, defaults, windowsIds):
self.__writeWarning(version)
windows, iana = self.__writeTables(self.writer.write, defaults, windowsIds)
windows, iana, aliased = self.__writeTables(self.writer.write, alias, defaults, windowsIds)
windows.write(self.writer.write, 'windowsIdData')
iana.write(self.writer.write, 'ianaIdData')
aliased.write(self.writer.write, 'aliasIdData')
def __writeWarning(self, version):
self.writer.write(f"""
/*
This part of the file was generated on {datetime.date.today()} from the
Common Locale Data Repository v{version} file supplemental/windowsZones.xml
Common Locale Data Repository v{version}
http://www.unicode.org/cldr/
@ -69,8 +70,19 @@ class ZoneIdWriter (SourceFileEditor):
""")
@staticmethod
def __writeTables(out, defaults, windowsIds):
windowsIdData, ianaIdData = ByteArrayData(), ByteArrayData()
def __writeTables(out, alias, defaults, windowsIds):
aliasIdData = ByteArrayData()
ianaIdData, windowsIdData = ByteArrayData(), ByteArrayData()
# Write IANA alias table
out('// Alias ID Index, Alias ID Index\n')
out('static constexpr AliasData aliasMappingTable[] = {\n')
for name, iana in sorted(alias.items()):
if name != iana:
out(' {{ {:6d},{:6d} }}, // {} -> {}\n'.format(
aliasIdData.append(name),
aliasIdData.append(iana), name, iana))
out('};\n\n')
# Write Windows/IANA table
out('// Windows ID Key, Territory Enum, IANA ID Index\n')
@ -111,7 +123,7 @@ class ZoneIdWriter (SourceFileEditor):
ianaIdData.append(' '.join(names)), offset, names[0]))
out('};\n')
return windowsIdData, ianaIdData
return windowsIdData, ianaIdData, aliasIdData
def main(out, err):
@ -145,9 +157,23 @@ def main(out, err):
if not dataFilePath.is_file():
parser.error(f'No such file: {dataFilePath}')
access = CldrAccess(cldrPath)
try:
version, defaults, winIds = CldrAccess(cldrPath).readWindowsTimeZones(
dict((name, ind) for ind, name in enumerate((x[0] for x in windowsIdList), 1)))
alias, ignored = access.bcp47Aliases()
# TODO: ignored maps IANA IDs to an extra-long name of the zone
except IOError as e:
parser.error(
f'Failed to open common/bcp47/timezone.xml: {e}')
return 1
except Error as e:
err.write('\n'.join(textwrap.wrap(
f'Failed to read bcp47/timezone.xml: {e}',
subsequent_indent=' ', width=80)) + '\n')
return 1
try:
version, defaults, winIds = access.readWindowsTimeZones(
{name: ind for ind, name in enumerate((x[0] for x in windowsIdList), 1)})
except IOError as e:
parser.error(
f'Failed to open common/supplemental/windowsZones.xml: {e}')
@ -158,11 +184,11 @@ def main(out, err):
subsequent_indent=' ', width=80)) + '\n')
return 1
out.write('Input file parsed, now writing data\n')
out.write('Input files parsed, now writing data\n')
try:
with ZoneIdWriter(dataFilePath, qtPath) as writer:
writer.write(version, defaults, winIds)
writer.write(version, alias, defaults, winIds)
except Exception as e:
err.write(f'\nError while updating timezone data: {e}\n')
return 1