1 /*
   2  * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.time.format;
  26 
  27 import java.util.HashMap;
  28 import java.util.Locale;
  29 import java.util.Map;
  30 
  31 /**
  32  * A helper class to map a zone name to metazone and back to the
  33  * appropriate zone id for the particular locale.
  34  * <p>
  35  * The zid<->metazone mappings are based on CLDR metaZones.xml.
  36  * The alias mappings are based on Link entries in tzdb data files and
  37  * CLDR's supplementalMetadata.xml.
  38  */
  39 class ZoneName {
  40 
  41     public static String toZid(String zid, Locale locale) {
  42         String mzone = zidToMzone.get(zid);
  43         if (mzone == null && aliases.containsKey(zid)) {
  44             zid = aliases.get(zid);
  45             mzone = zidToMzone.get(zid);
  46         }
  47         if (mzone != null) {
  48             Map<String, String> map = mzoneToZidL.get(mzone);
  49             if (map != null && map.containsKey(locale.getCountry())) {
  50                 zid = map.get(locale.getCountry());
  51             } else {
  52                 zid = mzoneToZid.get(mzone);
  53             }
  54         }
  55         return toZid(zid);
  56     }
  57 
  58     public static String toZid(String zid) {
  59         if (aliases.containsKey(zid)) {
  60             return aliases.get(zid);
  61         }
  62         return zid;
  63     }
  64 
  65     private static final String[] zidMap = new String[] {
  66         // From metaZones.xml
  67 %%%%ZIDMAP%%%%
  68 
  69         // From tzdb
  70         "Africa/Khartoum", "Africa_Central", "Africa/Maputo", // tzdata2017c
  71         "Africa/Windhoek", "Africa_Central", "Africa/Maputo", // tzdata2017c
  72         "Africa/Sao_Tome", "Africa_Western", "Africa/Lagos",  // tzdata2018c
  73     };
  74     private static final String[] mzoneMap = new String[] {
  75         // From metaZones.xml
  76 %%%%MZONEMAP%%%%
  77 
  78         // From tzdb
  79         "Africa_Western", "ST", "Africa/Sao_Tome", // tzdata2018c
  80     };
  81     private static final String[] aliasMap = new String[] {
  82         // From supplementalMetadata.xml
  83 %%%%DEPRECATED%%%%
  84 
  85         // From tzdb
  86         "Brazil/Acre", "America/Rio_Branco",
  87         "US/Indiana-Starke", "America/Indiana/Knox",
  88         "America/Atka", "America/Adak",
  89         "America/St_Barthelemy", "America/Guadeloupe",
  90         "Australia/North", "Australia/Darwin",
  91         "Europe/Zagreb", "Europe/Belgrade",
  92         "Etc/Universal", "Etc/UTC",
  93         "NZ-CHAT", "Pacific/Chatham",
  94         "Asia/Macao", "Asia/Macau",
  95         "Pacific/Yap", "Pacific/Chuuk",
  96         "Egypt", "Africa/Cairo",
  97         "US/Central", "America/Chicago",
  98         "Canada/Atlantic", "America/Halifax",
  99         "Brazil/East", "America/Sao_Paulo",
 100         "America/Cordoba", "America/Argentina/Cordoba",
 101         "US/Hawaii", "Pacific/Honolulu",
 102         "America/Louisville", "America/Kentucky/Louisville",
 103         "America/Shiprock", "America/Denver",
 104         "Australia/Canberra", "Australia/Sydney",
 105         "Asia/Chungking", "Asia/Chongqing",
 106         "Universal", "Etc/UTC",
 107         "US/Alaska", "America/Anchorage",
 108         "Asia/Ujung_Pandang", "Asia/Makassar",
 109         "Japan", "Asia/Tokyo",
 110         "Atlantic/Faeroe", "Atlantic/Faroe",
 111         "Asia/Istanbul", "Europe/Istanbul",
 112         "US/Pacific", "America/Los_Angeles",
 113         "Mexico/General", "America/Mexico_City",
 114         "Poland", "Europe/Warsaw",
 115         "Africa/Asmera", "Africa/Asmara",
 116         "Asia/Saigon", "Asia/Ho_Chi_Minh",
 117         "US/Michigan", "America/Detroit",
 118         "America/Argentina/ComodRivadavia", "America/Argentina/Catamarca",
 119         "W-SU", "Europe/Moscow",
 120         "Australia/ACT", "Australia/Sydney",
 121         "Asia/Calcutta", "Asia/Kolkata",
 122         "Arctic/Longyearbyen", "Europe/Oslo",
 123         "America/Knox_IN", "America/Indiana/Knox",
 124         "ROC", "Asia/Taipei",
 125         "Zulu", "Etc/UTC",
 126         "Australia/Yancowinna", "Australia/Broken_Hill",
 127         "Australia/West", "Australia/Perth",
 128         "Singapore", "Asia/Singapore",
 129         "Europe/Mariehamn", "Europe/Helsinki",
 130         "ROK", "Asia/Seoul",
 131         "America/Porto_Acre", "America/Rio_Branco",
 132         "Etc/Zulu", "Etc/UTC",
 133         "Canada/Yukon", "America/Whitehorse",
 134         "Europe/Vatican", "Europe/Rome",
 135         "Africa/Timbuktu", "Africa/Bamako",
 136         "America/Buenos_Aires", "America/Argentina/Buenos_Aires",
 137         "Canada/Pacific", "America/Vancouver",
 138         "US/Pacific-New", "America/Los_Angeles",
 139         "Mexico/BajaNorte", "America/Tijuana",
 140         "Europe/Guernsey", "Europe/London",
 141         "Asia/Tel_Aviv", "Asia/Jerusalem",
 142         "Chile/Continental", "America/Santiago",
 143         "Jamaica", "America/Jamaica",
 144         "Mexico/BajaSur", "America/Mazatlan",
 145         "Canada/Eastern", "America/Toronto",
 146         "Australia/Tasmania", "Australia/Hobart",
 147         "NZ", "Pacific/Auckland",
 148         "America/Lower_Princes", "America/Curacao",
 149         "GMT-", "Etc/GMT",
 150         "America/Rosario", "America/Argentina/Cordoba",
 151         "Libya", "Africa/Tripoli",
 152         "Asia/Ashkhabad", "Asia/Ashgabat",
 153         "Australia/NSW", "Australia/Sydney",
 154         "America/Marigot", "America/Guadeloupe",
 155         "Europe/Bratislava", "Europe/Prague",
 156         "Portugal", "Europe/Lisbon",
 157         "Etc/GMT-", "Etc/GMT",
 158         "Europe/San_Marino", "Europe/Rome",
 159         "Europe/Sarajevo", "Europe/Belgrade",
 160         "Antarctica/South_Pole", "Antarctica/McMurdo",
 161         "Canada/Central", "America/Winnipeg",
 162         "Etc/GMT", "Etc/GMT",
 163         "Europe/Isle_of_Man", "Europe/London",
 164         "America/Fort_Wayne", "America/Indiana/Indianapolis",
 165         "Eire", "Europe/Dublin",
 166         "America/Coral_Harbour", "America/Atikokan",
 167         "Europe/Nicosia", "Asia/Nicosia",
 168         "US/Samoa", "Pacific/Pago_Pago",
 169         "Hongkong", "Asia/Hong_Kong",
 170         "Canada/Saskatchewan", "America/Regina",
 171         "Asia/Thimbu", "Asia/Thimphu",
 172         "Kwajalein", "Pacific/Kwajalein",
 173         "GB", "Europe/London",
 174         "Chile/EasterIsland", "Pacific/Easter",
 175         "US/East-Indiana", "America/Indiana/Indianapolis",
 176         "Australia/LHI", "Australia/Lord_Howe",
 177         "Cuba", "America/Havana",
 178         "America/Jujuy", "America/Argentina/Jujuy",
 179         "US/Mountain", "America/Denver",
 180         "Atlantic/Jan_Mayen", "Europe/Oslo",
 181         "Europe/Tiraspol", "Europe/Chisinau",
 182         "Europe/Podgorica", "Europe/Belgrade",
 183         "US/Arizona", "America/Phoenix",
 184         "Navajo", "America/Denver",
 185         "Etc/Greenwich", "Etc/GMT",
 186         "Canada/Mountain", "America/Edmonton",
 187         "Iceland", "Atlantic/Reykjavik",
 188         "Australia/Victoria", "Australia/Melbourne",
 189         "Australia/South", "Australia/Adelaide",
 190         "Brazil/West", "America/Manaus",
 191         "Pacific/Ponape", "Pacific/Pohnpei",
 192         "Europe/Ljubljana", "Europe/Belgrade",
 193         "Europe/Jersey", "Europe/London",
 194         "Australia/Queensland", "Australia/Brisbane",
 195         "UTC", "Etc/UTC",
 196         "Canada/Newfoundland", "America/St_Johns",
 197         "Europe/Skopje", "Europe/Belgrade",
 198         "PRC", "Asia/Shanghai",
 199         "UCT", "Etc/UCT",
 200         "America/Mendoza", "America/Argentina/Mendoza",
 201         "Israel", "Asia/Jerusalem",
 202         "US/Eastern", "America/New_York",
 203         "Asia/Ulan_Bator", "Asia/Ulaanbaatar",
 204         "Turkey", "Europe/Istanbul",
 205         "GMT", "Etc/GMT",
 206         "US/Aleutian", "America/Adak",
 207         "Brazil/DeNoronha", "America/Noronha",
 208         "GB-Eire", "Europe/London",
 209         "Asia/Dacca", "Asia/Dhaka",
 210         "America/Ensenada", "America/Tijuana",
 211         "America/Catamarca", "America/Argentina/Catamarca",
 212         "Iran", "Asia/Tehran",
 213         "Greenwich", "Etc/GMT",
 214         "Pacific/Truk", "Pacific/Chuuk",
 215         "Pacific/Samoa", "Pacific/Pago_Pago",
 216         "America/Virgin", "America/St_Thomas",
 217         "Asia/Katmandu", "Asia/Kathmandu",
 218         "America/Indianapolis", "America/Indiana/Indianapolis",
 219         "Europe/Belfast", "Europe/London",
 220         "America/Kralendijk", "America/Curacao",
 221         "Asia/Rangoon", "Asia/Yangon",
 222     };
 223 
 224     private static final Map<String, String> zidToMzone = new HashMap<>();
 225     private static final Map<String, String> mzoneToZid = new HashMap<>();
 226     private static final Map<String, Map<String, String>> mzoneToZidL = new HashMap<>();
 227     private static final Map<String, String> aliases = new HashMap<>();
 228 
 229     static {
 230         for (int i = 0; i < zidMap.length; i += 3) {
 231             zidToMzone.put(zidMap[i], zidMap[i + 1]);
 232             mzoneToZid.put(zidMap[i + 1], zidMap[i + 2]);
 233         }
 234 
 235         for (int i = 0; i < mzoneMap.length; i += 3) {
 236             String mzone = mzoneMap[i];
 237             Map<String, String> map = mzoneToZidL.get(mzone);
 238             if (map == null) {
 239                 map = new HashMap<>();
 240                 mzoneToZidL.put(mzone, map);
 241             }
 242             map.put(mzoneMap[i + 1], mzoneMap[i + 2]);
 243         }
 244 
 245         for (int i = 0; i < aliasMap.length; i += 2) {
 246             aliases.put(aliasMap[i], aliasMap[i + 1]);
 247         }
 248     }
 249 }