diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp index 3a68277a6c8..7dd5dbf4234 100644 --- a/src/corelib/time/qtimezone.cpp +++ b/src/corelib/time/qtimezone.cpp @@ -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. diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp index f3dc43df6ad..4c01d095c4a 100644 --- a/src/corelib/time/qtimezoneprivate.cpp +++ b/src/corelib/time/qtimezoneprivate.cpp @@ -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); diff --git a/src/corelib/time/qtimezoneprivate_data_p.h b/src/corelib/time/qtimezoneprivate_data_p.h index 5174f06a0dc..794dd36b40b 100644 --- a/src/corelib/time/qtimezoneprivate_data_p.h +++ b/src/corelib/time/qtimezoneprivate_data_p.h @@ -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; } diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h index 5d57ed7558f..7034a7285c7 100644 --- a/src/corelib/time/qtimezoneprivate_p.h +++ b/src/corelib/time/qtimezoneprivate_p.h @@ -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, diff --git a/util/locale_database/cldr.py b/util/locale_database/cldr.py index 9e0bae96677..b610a1cfec7 100644 --- a/util/locale_database/cldr.py +++ b/util/locale_database/cldr.py @@ -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. diff --git a/util/locale_database/cldr2qtimezone.py b/util/locale_database/cldr2qtimezone.py index 485177c0bda..a2ee3019290 100755 --- a/util/locale_database/cldr2qtimezone.py +++ b/util/locale_database/cldr2qtimezone.py @@ -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