diff --git a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java index 55dd6a8d6ad..da8eba96dc7 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java @@ -787,10 +787,7 @@ private static Map extractZoneNames(Map map, Str String tzKey = Optional.ofNullable((String)handlerSupplMeta.get(tzid)) .orElse(tzid); // Follow link, if needed - String tzLink = null; - for (var k = tzKey; tzdbLinks.containsKey(k);) { - k = tzLink = tzdbLinks.get(k); - } + String tzLink = getTZDBLink(tzKey); if (tzLink == null && tzdbLinks.containsValue(tzKey)) { // reverse link search // this is needed as in tzdb, "America/Buenos_Aires" links to @@ -810,6 +807,13 @@ private static Map extractZoneNames(Map map, Str data = map.get(TIMEZONE_ID_PREFIX + tzLink); } + String meta = handlerMetaZones.get(tzKey); + if (meta == null && tzLink != null) { + // Check for tzLink + meta = handlerMetaZones.get(tzLink); + } + String metaKey = meta != null ? METAZONE_ID_PREFIX + meta : null; + if (data instanceof String[] tznames) { // Hack for UTC. UTC is an alias to Etc/UTC in CLDR if (tzid.equals("Etc/UTC") && !map.containsKey(TIMEZONE_ID_PREFIX + "UTC")) { @@ -819,24 +823,16 @@ private static Map extractZoneNames(Map map, Str } else { // TZDB short names tznames = Arrays.copyOf(tznames, tznames.length); - fillTZDBShortNames(tzid, tznames); + fillTZDBShortNames(tzKey, tznames); names.put(tzid, tznames); + if (meta != null && map.get(metaKey) instanceof String[] metaNames) { + recordMetazone(names, meta, tzKey, metaNames); + } } } else { - String meta = handlerMetaZones.get(tzKey); - if (meta == null && tzLink != null) { - // Check for tzLink - meta = handlerMetaZones.get(tzLink); - } if (meta != null) { - String metaKey = METAZONE_ID_PREFIX + meta; - data = map.get(metaKey); - if (data instanceof String[] tznames) { - // TZDB short names - tznames = Arrays.copyOf((String[])names.getOrDefault(metaKey, tznames), 6); - fillTZDBShortNames(tzid, tznames); - // Keep the metazone prefix here. - names.putIfAbsent(metaKey, tznames); + if (map.get(metaKey) instanceof String[] metaNames) { + recordMetazone(names, meta, tzKey, metaNames); names.put(tzid, meta); if (tzLink != null && availableIds.contains(tzLink)) { names.put(tzLink, meta); @@ -1484,12 +1480,12 @@ private static String flipIfNeeded(boolean inVanguard, String format) { * Fill the TZDB short names if there is no name provided by the CLDR */ private static void fillTZDBShortNames(String tzid, String[] names) { - var val = tzdbShortNamesMap.get(tzdbLinks.getOrDefault(tzid, tzid)); + var val = tzdbShortNamesMap.getOrDefault(tzid, tzdbShortNamesMap.get(getTZDBLink(tzid))); if (val != null) { var format = val.split(NBSP)[0]; var rule = val.split(NBSP)[1]; IntStream.of(1, 3, 5).forEach(i -> { - if (names[i] == null) { + if (names[i] == null || names[i].isEmpty()) { if (format.contains("%s")) { names[i] = switch (i) { case 1 -> format.formatted(tzdbSubstLetters.get(rule + NBSP + STD)); @@ -1511,6 +1507,28 @@ private static void fillTZDBShortNames(String tzid, String[] names) { } } + private static void recordMetazone(Map names, String meta, String tzid, String[] tznames) { + String zone001 = handlerMetaZones.zidMap().get(meta); + var tzLink = getTZDBLink(tzid); + + // Record the metazone names only from the default + // (001) zone, with short names filled from TZDB + if (canonicalTZMap.getOrDefault(tzid, tzid).equals(zone001) || + tzLink != null && canonicalTZMap.getOrDefault(tzLink, tzLink).equals(zone001)) { + tznames = Arrays.copyOf(tznames, tznames.length); + fillTZDBShortNames(tzid, tznames); + names.put(METAZONE_ID_PREFIX + meta, tznames); + } + } + + private static String getTZDBLink(String tzid) { + String tzLink = null; + for (var k = tzid; tzdbLinks.containsKey(k);) { + k = tzLink = tzdbLinks.get(k); + } + return tzLink; + } + /* * Convert TZDB offsets to JDK's offsets, eg, "-08" to "GMT-08:00". * If it cannot recognize the pattern, return the argument as is. diff --git a/test/jdk/sun/util/resources/cldr/TimeZoneNamesTest.java b/test/jdk/sun/util/resources/cldr/TimeZoneNamesTest.java index ed6fb2a58d8..3d6b3896150 100644 --- a/test/jdk/sun/util/resources/cldr/TimeZoneNamesTest.java +++ b/test/jdk/sun/util/resources/cldr/TimeZoneNamesTest.java @@ -24,6 +24,7 @@ /* * @test * @bug 8181157 8202537 8234347 8236548 8261279 8322647 8174269 8346948 + * 8382020 8384043 * @modules jdk.localedata * @summary Checks CLDR time zone names are generated correctly at * either build or runtime @@ -55,164 +56,211 @@ Object[][] sampleTZs() { // on the CLDR data upgrade. // no "metazone" zones - {"Asia/Srednekolymsk", Locale.US, "Srednekolymsk Standard Time", - "GMT+11:00", - "Srednekolymsk Daylight Time", - "GMT+12:00", - "Srednekolymsk Time", - "GMT+11:00"}, - {"Asia/Srednekolymsk", Locale.FRANCE, "Srednekolymsk (heure standard)", - "UTC+11:00", - "Srednekolymsk (heure d\u2019\u00e9t\u00e9)", - "UTC+12:00", - "heure : Srednekolymsk", - "UTC+11:00"}, - {"America/Punta_Arenas", Locale.US, "Punta Arenas Standard Time", - "GMT-03:00", - "Punta Arenas Daylight Time", - "GMT-02:00", - "Punta Arenas Time", - "GMT-03:00"}, - {"America/Punta_Arenas", Locale.FRANCE, "Punta Arenas (heure standard)", - "UTC\u221203:00", - "Punta Arenas (heure d\u2019\u00e9t\u00e9)", - "UTC\u221202:00", - "heure : Punta Arenas", - "UTC\u221203:00"}, - {"Asia/Famagusta", Locale.US, "Famagusta Standard Time", - "EET", - "Famagusta Daylight Time", - "EEST", - "Famagusta Time", - "EET"}, - {"Asia/Famagusta", Locale.FRANCE, "Famagouste (heure standard)", - "EET", - "Famagouste (heure d\u2019\u00e9t\u00e9)", - "EEST", - "heure : Famagouste", - "EET"}, - {"Europe/Astrakhan", Locale.US, "Astrakhan Standard Time", - "GMT+04:00", - "Astrakhan Daylight Time", - "GMT+05:00", - "Astrakhan Time", - "GMT+04:00"}, - {"Europe/Astrakhan", Locale.FRANCE, "Astrakhan (heure standard)", - "UTC+04:00", - "Astrakhan (heure d\u2019\u00e9t\u00e9)", - "UTC+05:00", - "heure : Astrakhan", - "UTC+04:00"}, - {"Europe/Saratov", Locale.US, "Saratov Standard Time", - "GMT+04:00", - "Saratov Daylight Time", - "GMT+05:00", - "Saratov Time", - "GMT+04:00"}, - {"Europe/Saratov", Locale.FRANCE, "Saratov (heure standard)", - "UTC+04:00", - "Saratov (heure d\u2019\u00e9t\u00e9)", - "UTC+05:00", - "heure : Saratov", - "UTC+04:00"}, - {"Europe/Ulyanovsk", Locale.US, "Ulyanovsk Standard Time", - "GMT+04:00", - "Ulyanovsk Daylight Time", - "GMT+05:00", - "Ulyanovsk Time", - "GMT+04:00"}, - {"Europe/Ulyanovsk", Locale.FRANCE, "Oulianovsk (heure standard)", - "UTC+04:00", - "Oulianovsk (heure d\u2019\u00e9t\u00e9)", - "UTC+05:00", - "heure : Oulianovsk", - "UTC+04:00"}, - {"Pacific/Bougainville", Locale.US, "Bougainville Standard Time", - "GMT+11:00", - "Bougainville Daylight Time", - "GMT+11:00", - "Bougainville Time", - "GMT+11:00"}, - {"Pacific/Bougainville", Locale.FRANCE, "Bougainville (heure standard)", - "UTC+11:00", - "Bougainville (heure d\u2019\u00e9t\u00e9)", - "UTC+11:00", - "heure : Bougainville", - "UTC+11:00"}, - {"Europe/Istanbul", Locale.US, "Istanbul Standard Time", - "GMT+03:00", - "Istanbul Daylight Time", - "GMT+04:00", - "Istanbul Time", - "GMT+03:00"}, - {"Europe/Istanbul", Locale.FRANCE, "Istanbul (heure standard)", - "UTC+03:00", - "Istanbul (heure d\u2019\u00e9t\u00e9)", - "UTC+04:00", - "heure : Istanbul", - "UTC+03:00"}, - {"Asia/Istanbul", Locale.US, "Istanbul Standard Time", - "GMT+03:00", - "Istanbul Daylight Time", - "GMT+04:00", - "Istanbul Time", - "GMT+03:00"}, - {"Asia/Istanbul", Locale.FRANCE, "Istanbul (heure standard)", - "UTC+03:00", - "Istanbul (heure d\u2019\u00e9t\u00e9)", - "UTC+04:00", - "heure : Istanbul", - "UTC+03:00"}, - {"Turkey", Locale.US, "Istanbul Standard Time", - "GMT+03:00", - "Istanbul Daylight Time", - "GMT+04:00", - "Istanbul Time", - "GMT+03:00"}, - {"Turkey", Locale.FRANCE, "Istanbul (heure standard)", - "UTC+03:00", - "Istanbul (heure d\u2019\u00e9t\u00e9)", - "UTC+04:00", - "heure : Istanbul", - "UTC+03:00"}, + {"Asia/Srednekolymsk", Locale.US, + "Srednekolymsk Standard Time", + "GMT+11:00", + "Srednekolymsk Daylight Time", + "GMT+12:00", + "Srednekolymsk Time", + "GMT+11:00"}, + {"Asia/Srednekolymsk", Locale.FRANCE, + "Srednekolymsk (heure standard)", + "UTC+11:00", + "Srednekolymsk (heure d\u2019\u00e9t\u00e9)", + "UTC+12:00", + "heure : Srednekolymsk", + "UTC+11:00"}, + {"America/Punta_Arenas", Locale.US, + "Punta Arenas Standard Time", + "GMT-03:00", + "Punta Arenas Daylight Time", + "GMT-02:00", + "Punta Arenas Time", + "GMT-03:00"}, + {"America/Punta_Arenas", Locale.FRANCE, + "Punta Arenas (heure standard)", + "UTC\u221203:00", + "Punta Arenas (heure d\u2019\u00e9t\u00e9)", + "UTC\u221202:00", + "heure : Punta Arenas", + "UTC\u221203:00"}, + {"Asia/Famagusta", Locale.US, + "Famagusta Standard Time", + "EET", + "Famagusta Daylight Time", + "EEST", + "Famagusta Time", + "EET"}, + {"Asia/Famagusta", Locale.FRANCE, + "Famagouste (heure standard)", + "EET", + "Famagouste (heure d\u2019\u00e9t\u00e9)", + "EEST", + "heure : Famagouste", + "EET"}, + {"Europe/Astrakhan", Locale.US, + "Astrakhan Standard Time", + "GMT+04:00", + "Astrakhan Daylight Time", + "GMT+05:00", + "Astrakhan Time", + "GMT+04:00"}, + {"Europe/Astrakhan", Locale.FRANCE, + "Astrakhan (heure standard)", + "UTC+04:00", + "Astrakhan (heure d\u2019\u00e9t\u00e9)", + "UTC+05:00", + "heure : Astrakhan", + "UTC+04:00"}, + {"Europe/Saratov", Locale.US, + "Saratov Standard Time", + "GMT+04:00", + "Saratov Daylight Time", + "GMT+05:00", + "Saratov Time", + "GMT+04:00"}, + {"Europe/Saratov", Locale.FRANCE, + "Saratov (heure standard)", + "UTC+04:00", + "Saratov (heure d\u2019\u00e9t\u00e9)", + "UTC+05:00", + "heure : Saratov", + "UTC+04:00"}, + {"Europe/Ulyanovsk", Locale.US, + "Ulyanovsk Standard Time", + "GMT+04:00", + "Ulyanovsk Daylight Time", + "GMT+05:00", + "Ulyanovsk Time", + "GMT+04:00"}, + {"Europe/Ulyanovsk", Locale.FRANCE, + "Oulianovsk (heure standard)", + "UTC+04:00", + "Oulianovsk (heure d\u2019\u00e9t\u00e9)", + "UTC+05:00", + "heure : Oulianovsk", + "UTC+04:00"}, + {"Pacific/Bougainville", Locale.US, + "Bougainville Standard Time", + "GMT+11:00", + "Bougainville Daylight Time", + "GMT+11:00", + "Bougainville Time", + "GMT+11:00"}, + {"Pacific/Bougainville", Locale.FRANCE, + "Bougainville (heure standard)", + "UTC+11:00", + "Bougainville (heure d\u2019\u00e9t\u00e9)", + "UTC+11:00", + "heure : Bougainville", + "UTC+11:00"}, + {"Europe/Istanbul", Locale.US, + "Istanbul Standard Time", + "GMT+03:00", + "Istanbul Daylight Time", + "GMT+04:00", + "Istanbul Time", + "GMT+03:00"}, + {"Europe/Istanbul", Locale.FRANCE, + "Istanbul (heure standard)", + "UTC+03:00", + "Istanbul (heure d\u2019\u00e9t\u00e9)", + "UTC+04:00", + "heure : Istanbul", + "UTC+03:00"}, + {"Asia/Istanbul", Locale.US, + "Istanbul Standard Time", + "GMT+03:00", + "Istanbul Daylight Time", + "GMT+04:00", + "Istanbul Time", + "GMT+03:00"}, + {"Asia/Istanbul", Locale.FRANCE, + "Istanbul (heure standard)", + "UTC+03:00", + "Istanbul (heure d\u2019\u00e9t\u00e9)", + "UTC+04:00", + "heure : Istanbul", + "UTC+03:00"}, + {"Turkey", Locale.US, + "Istanbul Standard Time", + "GMT+03:00", + "Istanbul Daylight Time", + "GMT+04:00", + "Istanbul Time", + "GMT+03:00"}, + {"Turkey", Locale.FRANCE, + "Istanbul (heure standard)", + "UTC+03:00", + "Istanbul (heure d\u2019\u00e9t\u00e9)", + "UTC+04:00", + "heure : Istanbul", + "UTC+03:00"}, // Short names derived from TZDB at build time - {"Europe/Lisbon", Locale.US, "Western European Standard Time", - "WET", - "Western European Summer Time", - "WEST", - "Western European Time", - "WET"}, - {"Atlantic/Azores", Locale.US, "Azores Standard Time", - "GMT-01:00", - "Azores Summer Time", - "GMT", - "Azores Time", - "GMT-01:00"}, - {"Australia/Perth", Locale.US, "Australian Western Standard Time", - "AWST", - "Australian Western Daylight Time", - "AWDT", - "Australian Western Time", - "AWT"}, - {"Africa/Harare", Locale.US, "Central Africa Time", - "CAT", - "Harare Daylight Time", - "CAT", - "Harare Time", - "CAT"}, - {"Europe/Dublin", Locale.US, "Greenwich Mean Time", - "GMT", - "Irish Standard Time", - "IST", - "Dublin Time", - "GMT"}, - {"Pacific/Gambier", Locale.US, "Gambier Time", - "GMT-09:00", - "Gambier Daylight Time", - "GMT-09:00", - "Gambier Time", - "GMT-09:00"}, + {"Europe/Lisbon", Locale.US, + "Western European Standard Time", + "WET", + "Western European Summer Time", + "WEST", + "Western European Time", + "WET"}, + {"Atlantic/Azores", Locale.US, + "Azores Standard Time", + "GMT-01:00", + "Azores Summer Time", + "GMT", + "Azores Time", + "GMT-01:00"}, + {"Australia/Perth", Locale.US, + "Australian Western Standard Time", + "AWST", + "Australian Western Daylight Time", + "AWDT", + "Australian Western Time", + "AWT"}, + {"Africa/Harare", Locale.US, + "Central Africa Time", + "CAT", + "Harare Daylight Time", + "CAT", + "Harare Time", + "CAT"}, + {"Europe/Dublin", Locale.US, + "Greenwich Mean Time", + "GMT", + "Irish Standard Time", + "IST", + "Dublin Time", + "GMT"}, + {"Pacific/Gambier", Locale.US, + "Gambier Time", + "GMT-09:00", + "Gambier Daylight Time", + "GMT-09:00", + "Gambier Time", + "GMT-09:00"}, + + // Hawaii/Aleutian + // + // CLDR v47 does not contain CLDR-18531 + // so both Pacific/Honolulu and America/Adak + // share the same long names and differ only + // on the short names. + {"Pacific/Honolulu", Locale.US, + "Hawaii-Aleutian Standard Time", + "HST", + "Hawaii-Aleutian Daylight Time", + "HDT", + "Hawaii-Aleutian Time", + "HST"}, + {"America/Adak", Locale.US, + "Hawaii-Aleutian Standard Time", + "HAST", + "Hawaii-Aleutian Daylight Time", + "HADT", + "Hawaii-Aleutian Time", + "HAT"}, }; }