--- old/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java 2019-12-12 14:00:07.000000000 -0800 +++ new/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java 2019-12-12 14:00:07.000000000 -0800 @@ -113,6 +113,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.TimeZone; import java.util.concurrent.ConcurrentHashMap; @@ -4123,7 +4124,8 @@ } Locale locale = context.getLocale(); boolean isCaseSensitive = context.isCaseSensitive(); - Set regionIds = ZoneRulesProvider.getAvailableZoneIds(); + Set regionIds = new HashSet<>(ZoneRulesProvider.getAvailableZoneIds()); + Set nonRegionIds = new HashSet<>(64); int regionIdsSize = regionIds.size(); Map>> cached = @@ -4139,7 +4141,8 @@ zoneStrings = TimeZoneNameUtility.getZoneStrings(locale); for (String[] names : zoneStrings) { String zid = names[0]; - if (!regionIds.contains(zid)) { + if (!regionIds.remove(zid)) { + nonRegionIds.add(zid); continue; } tree.add(zid, zid); // don't convert zid -> metazone @@ -4149,12 +4152,27 @@ tree.add(names[i], zid); } } + + // add names for provider's custom ids + final PrefixTree t = tree; + regionIds.stream() + .filter(zid -> !zid.startsWith("Etc") && !zid.startsWith("GMT")) + .forEach(cid -> { + String[] cidNames = TimeZoneNameUtility.retrieveDisplayNames(cid, locale); + int i = textStyle == TextStyle.FULL ? 1 : 2; + for (; i < cidNames.length; i += 2) { + if (cidNames[i] != null && !cidNames[i].isEmpty()) { + t.add(cidNames[i], cid); + } + } + }); + // if we have a set of preferred zones, need a copy and // add the preferred zones again to overwrite if (preferredZones != null) { for (String[] names : zoneStrings) { String zid = names[0]; - if (!preferredZones.contains(zid) || !regionIds.contains(zid)) { + if (!preferredZones.contains(zid) || nonRegionIds.contains(zid)) { continue; } int i = textStyle == TextStyle.FULL ? 1 : 2;