< prev index next >

src/java.base/share/classes/sun/util/cldr/CLDRTimeZoneNameProviderImpl.java

Print this page
rev 54003 : [mq]: 8218948


  56             Arrays.stream(ZoneInfoFile.getZoneIds())
  57                 .sorted()
  58                 .toArray(String[]::new);
  59     }
  60 
  61     // display name array indexes
  62     private static final int INDEX_TZID         = 0;
  63     private static final int INDEX_STD_LONG     = 1;
  64     private static final int INDEX_STD_SHORT    = 2;
  65     private static final int INDEX_DST_LONG     = 3;
  66     private static final int INDEX_DST_SHORT    = 4;
  67     private static final int INDEX_GEN_LONG     = 5;
  68     private static final int INDEX_GEN_SHORT    = 6;
  69 
  70     public CLDRTimeZoneNameProviderImpl(Type type, Set<String> langtags) {
  71         super(type, langtags);
  72     }
  73 
  74     @Override
  75     protected String[] getDisplayNameArray(String id, Locale locale) {
  76         String tzid = TimeZoneNameUtility.canonicalTZID(id).orElse(id);
  77         String[] namesSuper = super.getDisplayNameArray(tzid, locale);








  78 
  79         if (Objects.nonNull(namesSuper)) {
  80             // CLDR's resource bundle has an translated entry for this id.
  81             // Fix up names if needed, either missing or no-inheritance
  82             namesSuper[INDEX_TZID] = id;
  83 
  84             // Check if standard long name exists. If not, try to retrieve the name
  85             // from language only locale resources. E.g., "Europe/London"
  86             // for en-GB only contains DST names
  87             if (!exists(namesSuper, INDEX_STD_LONG) && !locale.getCountry().isEmpty()) {
  88                 String[] names =
  89                         getDisplayNameArray(id, Locale.forLanguageTag(locale.getLanguage()));
  90                 if (exists(names, INDEX_STD_LONG)) {
  91                     namesSuper[INDEX_STD_LONG] = names[INDEX_STD_LONG];
  92                 }
  93             }
  94 
  95             for(int i = INDEX_STD_LONG; i < namesSuper.length; i++) { // index 0 is the 'id' itself
  96                 switch (namesSuper[i]) {
  97                 case "":
  98                     // Fill in empty elements
  99                     deriveFallbackName(namesSuper, i, locale,
 100                             namesSuper[INDEX_DST_LONG].isEmpty());
 101                     break;
 102                 case NO_INHERITANCE_MARKER:
 103                     // CLDR's "no inheritance marker"
 104                     namesSuper[i] = toGMTFormat(id, i == INDEX_DST_LONG || i == INDEX_DST_SHORT,
 105                                                 i % 2 != 0, locale);
 106                     break;
 107                 default:
 108                     break;
 109                 }
 110             }
 111             return namesSuper;
 112         } else {
 113             // Derive the names for this id. Validate the id first.
 114             if (Arrays.binarySearch(AVAILABLE_IDS.INSTANCE, id) >= 0) {
 115                 String[] names = new String[INDEX_GEN_SHORT + 1];
 116                 names[INDEX_TZID] = id;
 117                 deriveFallbackNames(names, locale);
 118                 return names;
 119             }
 120         }


 124 
 125     @Override
 126     protected String[][] getZoneStrings(Locale locale) {
 127         // Use English for the ROOT locale
 128         locale = locale.equals(Locale.ROOT) ? Locale.ENGLISH : locale;
 129         String[][] ret = super.getZoneStrings(locale);
 130 
 131         // Fill in for the empty names.
 132         // English names are prefilled for performance.
 133         if (!locale.equals(Locale.ENGLISH) &&
 134             !locale.equals(Locale.US)) {
 135             for (int zoneIndex = 0; zoneIndex < ret.length; zoneIndex++) {
 136                 deriveFallbackNames(ret[zoneIndex], locale);
 137             }
 138         }
 139         return ret;
 140     }
 141 
 142     // Derive fallback time zone name according to LDML's logic
 143     private void deriveFallbackNames(String[] names, Locale locale) {

 144         for (int i = INDEX_STD_LONG; i <= INDEX_GEN_SHORT; i++) {
 145             deriveFallbackName(names, i, locale, false);
 146         }
 147     }
 148 
 149     private void deriveFallbackName(String[] names, int index, Locale locale, boolean noDST) {


 150         if (exists(names, index)) {
 151             if (names[index].equals(NO_INHERITANCE_MARKER)) {
 152                 // CLDR's "no inheritance marker"
 153                 names[index] = toGMTFormat(names[INDEX_TZID],
 154                                     index == INDEX_DST_LONG || index == INDEX_DST_SHORT,
 155                                     index % 2 != 0, locale);
 156             }
 157             return;
 158         }
 159 
 160         // Check if COMPAT can substitute the name
 161         if (LocaleProviderAdapter.getAdapterPreference().contains(Type.JRE)) {
 162             String[] compatNames = (String[])LocaleProviderAdapter.forJRE()
 163                 .getLocaleResources(locale)
 164                 .getTimeZoneNames(names[INDEX_TZID]);
 165             if (compatNames != null) {
 166                 for (int i = INDEX_STD_LONG; i <= INDEX_GEN_SHORT; i++) {
 167                     // Assumes COMPAT has no empty slots
 168                     if (i == index || !exists(names, i)) {
 169                         names[i] = compatNames[i];
 170                     }
 171                 }
 172                 return;
 173             }
 174         }
 175 
 176         // Type Fallback
 177         if (noDST && typeFallback(names, index)) {
 178             return;
 179         }
 180 
 181         // Region Fallback
 182         if (regionFormatFallback(names, index, locale)) {
 183             return;
 184         }
 185 
 186         // last resort
 187         String id = names[INDEX_TZID].toUpperCase(Locale.ROOT);
 188         if (!id.startsWith("UT")) {
 189             names[index] = toGMTFormat(names[INDEX_TZID],
 190                                        index == INDEX_DST_LONG || index == INDEX_DST_SHORT,
 191                                        index % 2 != 0,
 192                                        locale);
 193             // aliases of "GMT" timezone.
 194             if ((exists(names, INDEX_STD_LONG)) && (id.startsWith("Etc/")
 195                     || id.startsWith("GMT") || id.startsWith("Greenwich"))) {
 196                 switch (id) {
 197                 case "Etc/GMT":
 198                 case "Etc/GMT-0":
 199                 case "Etc/GMT+0":
 200                 case "Etc/GMT0":
 201                 case "GMT+0":
 202                 case "GMT-0":
 203                 case "GMT0":
 204                 case "Greenwich":
 205                     names[INDEX_DST_LONG] = names[INDEX_GEN_LONG] = names[INDEX_STD_LONG];
 206                     break;
 207                 }
 208             }
 209         }


 273 
 274         if (offset == 0) {
 275             return fd.getString("timezone.gmtZeroFormat");
 276         } else {
 277             String gmtFormat = fd.getString("timezone.gmtFormat");
 278             String hourFormat = fd.getString("timezone.hourFormat");
 279 
 280             if (offset > 0) {
 281                 hourFormat = hourFormat.substring(0, hourFormat.indexOf(";"));
 282             } else {
 283                 hourFormat = hourFormat.substring(hourFormat.indexOf(";") + 1);
 284                 offset = -offset;
 285             }
 286             hourFormat = hourFormat
 287                 .replaceFirst("H+", (isShort ? "\\%1\\$d" : "\\%1\\$02d"))
 288                 .replaceFirst("m+", "\\%2\\$02d");
 289             return MessageFormat.format(gmtFormat,
 290                     String.format(l, hourFormat, offset / 60, offset % 60));
 291         }
 292     }





























 293 }


  56             Arrays.stream(ZoneInfoFile.getZoneIds())
  57                 .sorted()
  58                 .toArray(String[]::new);
  59     }
  60 
  61     // display name array indexes
  62     private static final int INDEX_TZID         = 0;
  63     private static final int INDEX_STD_LONG     = 1;
  64     private static final int INDEX_STD_SHORT    = 2;
  65     private static final int INDEX_DST_LONG     = 3;
  66     private static final int INDEX_DST_SHORT    = 4;
  67     private static final int INDEX_GEN_LONG     = 5;
  68     private static final int INDEX_GEN_SHORT    = 6;
  69 
  70     public CLDRTimeZoneNameProviderImpl(Type type, Set<String> langtags) {
  71         super(type, langtags);
  72     }
  73 
  74     @Override
  75     protected String[] getDisplayNameArray(String id, Locale locale) {
  76         // Use English for the ROOT locale
  77         locale = locale.equals(Locale.ROOT) ? Locale.ENGLISH : locale;
  78         String[] namesSuper = super.getDisplayNameArray(id, locale);
  79 
  80         if (namesSuper == null) {
  81             // try canonical id instead
  82             namesSuper = super.getDisplayNameArray(
  83                 TimeZoneNameUtility.canonicalTZID(id).orElse(id),
  84                 locale);
  85         }
  86 
  87         if (namesSuper != null) {
  88             // CLDR's resource bundle has an translated entry for this id.
  89             // Fix up names if needed, either missing or no-inheritance
  90             namesSuper[INDEX_TZID] = id;
  91 











  92             for(int i = INDEX_STD_LONG; i < namesSuper.length; i++) { // index 0 is the 'id' itself
  93                 switch (namesSuper[i]) {
  94                 case "":
  95                     // Fill in empty elements
  96                     deriveFallbackName(namesSuper, i, locale,
  97                                        !exists(namesSuper, INDEX_DST_LONG));
  98                     break;
  99                 case NO_INHERITANCE_MARKER:
 100                     // CLDR's "no inheritance marker"
 101                     namesSuper[i] = toGMTFormat(id, i == INDEX_DST_LONG || i == INDEX_DST_SHORT,
 102                                                 i % 2 != 0, locale);
 103                     break;
 104                 default:
 105                     break;
 106                 }
 107             }
 108             return namesSuper;
 109         } else {
 110             // Derive the names for this id. Validate the id first.
 111             if (Arrays.binarySearch(AVAILABLE_IDS.INSTANCE, id) >= 0) {
 112                 String[] names = new String[INDEX_GEN_SHORT + 1];
 113                 names[INDEX_TZID] = id;
 114                 deriveFallbackNames(names, locale);
 115                 return names;
 116             }
 117         }


 121 
 122     @Override
 123     protected String[][] getZoneStrings(Locale locale) {
 124         // Use English for the ROOT locale
 125         locale = locale.equals(Locale.ROOT) ? Locale.ENGLISH : locale;
 126         String[][] ret = super.getZoneStrings(locale);
 127 
 128         // Fill in for the empty names.
 129         // English names are prefilled for performance.
 130         if (!locale.equals(Locale.ENGLISH) &&
 131             !locale.equals(Locale.US)) {
 132             for (int zoneIndex = 0; zoneIndex < ret.length; zoneIndex++) {
 133                 deriveFallbackNames(ret[zoneIndex], locale);
 134             }
 135         }
 136         return ret;
 137     }
 138 
 139     // Derive fallback time zone name according to LDML's logic
 140     private void deriveFallbackNames(String[] names, Locale locale) {
 141         boolean noDST = !exists(names, INDEX_DST_LONG);
 142         for (int i = INDEX_STD_LONG; i <= INDEX_GEN_SHORT; i++) {
 143             deriveFallbackName(names, i, locale, noDST);
 144         }
 145     }
 146 
 147     private void deriveFallbackName(String[] names, int index, Locale locale, boolean noDST) {
 148         String id = names[INDEX_TZID];
 149 
 150         if (exists(names, index)) {
 151             if (names[index].equals(NO_INHERITANCE_MARKER)) {
 152                 // CLDR's "no inheritance marker"
 153                 names[index] = toGMTFormat(id,
 154                                     index == INDEX_DST_LONG || index == INDEX_DST_SHORT,
 155                                     index % 2 != 0, locale);
 156             }
 157             return;
 158         }
 159 
 160         // Check if COMPAT can substitute the name
 161         if (LocaleProviderAdapter.getAdapterPreference().contains(Type.JRE)) {
 162             String[] compatNames = (String[])LocaleProviderAdapter.forJRE()
 163                 .getLocaleResources(mapChineseLocale(locale))
 164                 .getTimeZoneNames(id);
 165             if (compatNames != null) {
 166                 for (int i = INDEX_STD_LONG; i <= INDEX_GEN_SHORT; i++) {
 167                     // Assumes COMPAT has no empty slots
 168                     if (i == index || !exists(names, i)) {
 169                         names[i] = compatNames[i];
 170                     }
 171                 }
 172                 return;
 173             }
 174         }
 175 
 176         // Type Fallback
 177         if (noDST && typeFallback(names, index)) {
 178             return;
 179         }
 180 
 181         // Region Fallback
 182         if (regionFormatFallback(names, index, locale)) {
 183             return;
 184         }
 185 
 186         // last resort
 187         if (!id.toUpperCase(Locale.ROOT).startsWith("UT")) {
 188             names[index] = toGMTFormat(id,

 189                                        index == INDEX_DST_LONG || index == INDEX_DST_SHORT,
 190                                        index % 2 != 0,
 191                                        locale);
 192             // aliases of "GMT" timezone.
 193             if ((exists(names, INDEX_STD_LONG)) && (id.startsWith("Etc/")
 194                     || id.startsWith("GMT") || id.startsWith("Greenwich"))) {
 195                 switch (id) {
 196                 case "Etc/GMT":
 197                 case "Etc/GMT-0":
 198                 case "Etc/GMT+0":
 199                 case "Etc/GMT0":
 200                 case "GMT+0":
 201                 case "GMT-0":
 202                 case "GMT0":
 203                 case "Greenwich":
 204                     names[INDEX_DST_LONG] = names[INDEX_GEN_LONG] = names[INDEX_STD_LONG];
 205                     break;
 206                 }
 207             }
 208         }


 272 
 273         if (offset == 0) {
 274             return fd.getString("timezone.gmtZeroFormat");
 275         } else {
 276             String gmtFormat = fd.getString("timezone.gmtFormat");
 277             String hourFormat = fd.getString("timezone.hourFormat");
 278 
 279             if (offset > 0) {
 280                 hourFormat = hourFormat.substring(0, hourFormat.indexOf(";"));
 281             } else {
 282                 hourFormat = hourFormat.substring(hourFormat.indexOf(";") + 1);
 283                 offset = -offset;
 284             }
 285             hourFormat = hourFormat
 286                 .replaceFirst("H+", (isShort ? "\\%1\\$d" : "\\%1\\$02d"))
 287                 .replaceFirst("m+", "\\%2\\$02d");
 288             return MessageFormat.format(gmtFormat,
 289                     String.format(l, hourFormat, offset / 60, offset % 60));
 290         }
 291     }
 292 
 293     // Mapping CLDR's Simplified/Traditional Chinese resources
 294     // to COMPAT's zh-CN/TW
 295     private Locale mapChineseLocale(Locale locale) {
 296         if (locale.getLanguage() == "zh") {
 297             switch (locale.getScript()) {
 298                 case "Hans":
 299                     return Locale.CHINA;
 300                 case "Hant":
 301                     return Locale.TAIWAN;
 302                 case "":
 303                     // no script, guess from country code.
 304                     switch (locale.getCountry()) {
 305                         case "":
 306                         case "CN":
 307                         case "SG":
 308                             return Locale.CHINA;
 309                         case "HK":
 310                         case "MO":
 311                         case "TW":
 312                             return Locale.TAIWAN;
 313                     }
 314                     break;
 315             }
 316         }
 317 
 318         // no need to map
 319         return locale;
 320     }
 321 }
< prev index next >