1 11 package com.ibm.icu.impl; 12 13 import java.text.ParsePosition ; 14 import java.util.Arrays ; 15 import java.util.ArrayList ; 16 import java.util.Collections ; 17 import java.util.HashMap ; 18 import java.util.Map ; 19 import java.util.MissingResourceException ; 20 import java.util.Set ; 21 import java.util.TreeMap ; 22 import java.util.TreeSet ; 23 import java.util.Vector ; 24 25 import com.ibm.icu.text.MessageFormat; 26 import com.ibm.icu.text.NumberFormat; 27 import com.ibm.icu.text.SimpleDateFormat; 28 import com.ibm.icu.util.SimpleTimeZone; 29 import com.ibm.icu.util.TimeZone; 30 import com.ibm.icu.util.ULocale; 31 import com.ibm.icu.util.UResourceBundle; 32 33 47 public final class ZoneMeta { 48 private static final boolean ASSERT = false; 49 50 60 public static synchronized String [] getAvailableIDs(String country) { 61 if(!getOlsonMeta()){ 62 return EMPTY; 63 } 64 try{ 65 ICUResourceBundle top = (ICUResourceBundle)ICUResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "zoneinfo", ICUResourceBundle.ICU_DATA_CLASS_LOADER); 66 ICUResourceBundle regions = top.get(kREGIONS); 67 ICUResourceBundle names = top.get(kNAMES); ICUResourceBundle temp = regions.get(country); 69 int[] vector = temp.getIntVector(); 70 if (ASSERT) Assert.assrt("vector.length>0", vector.length>0); 71 String [] ret = new String [vector.length]; 72 for (int i=0; i<vector.length; ++i) { 73 if (ASSERT) Assert.assrt("vector[i] >= 0 && vector[i] < OLSON_ZONE_COUNT", 74 vector[i] >= 0 && vector[i] < OLSON_ZONE_COUNT); 75 ret[i] = names.getString(vector[i]); 76 } 77 return ret; 78 }catch(MissingResourceException ex){ 79 } 81 return EMPTY; 82 } 83 public static synchronized String [] getAvailableIDs() { 84 if(!getOlsonMeta()){ 85 return EMPTY; 86 } 87 try{ 88 ICUResourceBundle top = (ICUResourceBundle)ICUResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "zoneinfo", ICUResourceBundle.ICU_DATA_CLASS_LOADER); 89 ICUResourceBundle names = top.get(kNAMES); return names.getStringArray(); 91 }catch(MissingResourceException ex){ 92 } 94 return EMPTY; 95 } 96 public static synchronized String [] getAvailableIDs(int offset){ 97 Vector vector = new Vector (); 98 for (int i=0; i<OLSON_ZONE_COUNT; ++i) { 99 String unistr; 100 if ((unistr=getID(i))!=null) { 101 TimeZone z = TimeZone.getTimeZone(unistr); 103 if (z != null && z.getID().equals(unistr) && 106 z.getRawOffset() == offset) { 107 vector.add(unistr); 108 } 109 } 110 } 111 if(!vector.isEmpty()){ 112 String [] strings = new String [vector.size()]; 113 return (String [])vector.toArray(strings); 114 } 115 return EMPTY; 116 } 117 private static String getID(int i) { 118 try{ 119 ICUResourceBundle top = (ICUResourceBundle)ICUResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "zoneinfo", ICUResourceBundle.ICU_DATA_CLASS_LOADER); 120 ICUResourceBundle names = top.get(kNAMES); return names.getString(i); 122 }catch(MissingResourceException ex){ 123 } 125 return null; 126 } 127 140 public static synchronized int countEquivalentIDs(String id) { 141 142 ICUResourceBundle res = openOlsonResource(id); 143 int size = res.getSize(); 144 if (size == 4 || size == 6) { 145 ICUResourceBundle r=res.get(size-1); 146 int[] v = r.getIntVector(); 148 return v.length; 149 } 150 return 0; 151 } 152 153 171 public static synchronized String getEquivalentID(String id, int index) { 172 String result=""; 173 ICUResourceBundle res = openOlsonResource(id); 174 int zone = -1; 175 int size = res.getSize(); 176 if (size == 4 || size == 6) { 177 ICUResourceBundle r = res.get(size-1); 178 int[] v = r.getIntVector(); 179 if (index >= 0 && index < size && getOlsonMeta()) { 180 zone = v[index]; 181 } 182 } 183 if (zone >= 0) { 184 ICUResourceBundle top = (ICUResourceBundle)ICUResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "zoneinfo", ICUResourceBundle.ICU_DATA_CLASS_LOADER); 185 ICUResourceBundle ares = top.get(kNAMES); result = ares.getString(zone); 187 188 } 189 return result; 190 } 191 192 220 private static String [] getCanonicalInfo(String id) { 221 if (canonicalMap == null) { 222 Map m = new HashMap (); 223 for (int i = 0; i < ZoneInfoExt.CLDR_INFO.length; ++i) { 224 String [] clist = ZoneInfoExt.CLDR_INFO[i]; 225 String c = clist[0]; 226 m.put(c, clist); 227 for (int j = 3; j < clist.length; ++j) { 228 m.put(clist[j], clist); 229 } 230 } 231 synchronized (ZoneMeta.class) { 232 canonicalMap = m; 233 } 234 } 235 236 return (String [])canonicalMap.get(id); 237 } 238 private static Map canonicalMap = null; 239 240 244 public static String getCanonicalID(String tzid) { 245 String [] info = getCanonicalInfo(tzid); 246 if (info != null) { 247 return info[0]; 248 } 249 return tzid; 250 } 251 252 256 public static String getCanonicalCountry(String tzid) { 257 String [] info = getCanonicalInfo(tzid); 258 if (info != null) { 259 return info[1]; 260 } 261 return null; 262 } 263 264 270 public static String getSingleCountry(String tzid) { 271 String [] info = getCanonicalInfo(tzid); 272 if (info != null && info[2] != null) { 273 return info[1]; 274 } 275 return null; 276 } 277 278 281 public static String displayFallback(String tzid, String city, ULocale locale) { 282 String [] info = getCanonicalInfo(tzid); 283 if (info == null) { 284 return null; } 286 287 String country_code = info[1]; 288 if (country_code == null) { 289 return null; } 291 292 String country = null; 293 if (country_code != null) { 294 ICUResourceBundle rb = 295 (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, locale); 296 if (rb.getLoadingStatus() != rb.FROM_ROOT && rb.getLoadingStatus() != rb.FROM_DEFAULT) { 297 country = ULocale.getDisplayCountry("xx_" + country_code, locale); 298 } 299 if (country == null || country.length() == 0) country = country_code; 300 } 301 302 if (info[2] != null) { return displayRegion(country, locale); 306 } 307 308 if (city == null) { 309 city = tzid.substring(tzid.lastIndexOf('/')+1).replace('_',' '); 310 } 311 312 String flbPat = getTZLocalizationInfo(locale, FALLBACK_FORMAT); 313 MessageFormat mf = new MessageFormat(flbPat); 314 315 return mf.format(new Object [] { city, country }); 316 } 317 318 public static String displayRegion(String cityOrCountry, ULocale locale) { 319 String regPat = getTZLocalizationInfo(locale, REGION_FORMAT); 320 MessageFormat mf = new MessageFormat(regPat); 321 return mf.format(new Object [] { cityOrCountry }); 322 } 323 324 public static String displayGMT(long value, ULocale locale) { 325 String msgpat = getTZLocalizationInfo(locale, GMT); 326 String dtepat = getTZLocalizationInfo(locale, HOUR); 327 328 int n = dtepat.indexOf(';'); 329 if (n != -1) { 330 if (value < 0) { 331 value = - value; 332 dtepat = dtepat.substring(n+1); 333 } else { 334 dtepat = dtepat.substring(0, n); 335 } 336 } 337 338 final long mph = 3600000; 339 final long mpm = 60000; 340 341 SimpleDateFormat sdf = new SimpleDateFormat(dtepat, locale); 342 sdf.setTimeZone(TimeZone.getTimeZone("GMT")); 343 String res = sdf.format(new Long (value)); 344 MessageFormat mf = new MessageFormat(msgpat); 345 res = mf.format(new Object [] { res }); 346 return res; 347 } 348 349 public static final String 350 HOUR = "hourFormat", 351 GMT = "gmtFormat", 352 REGION_FORMAT = "regionFormat", 353 FALLBACK_FORMAT = "fallbackFormat", 354 ZONE_STRINGS = "zoneStrings", 355 FORWARD_SLASH = "/"; 356 357 361 public static String getTZLocalizationInfo(ULocale locale, String format) { 362 ICUResourceBundle bundle = (ICUResourceBundle) ICUResourceBundle.getBundleInstance(locale); 363 return bundle.getStringWithFallback(ZONE_STRINGS+FORWARD_SLASH+format); 364 } 365 366 private static Set getValidIDs() { 367 Set valid = new TreeSet (); 371 valid.addAll(Arrays.asList(java.util.TimeZone.getAvailableIDs())); 372 return valid; 373 } 374 375 378 private static final String [] EMPTY = new String [0]; 379 380 381 382 389 public static ICUResourceBundle openOlsonResource(String id) 390 { 391 if(!getOlsonMeta()){ 392 return null; 393 } 394 ICUResourceBundle top = (ICUResourceBundle)ICUResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "zoneinfo", ICUResourceBundle.ICU_DATA_CLASS_LOADER); 395 ICUResourceBundle res = getZoneByName(top, id); 396 if (res.getSize() <= 1 && getOlsonMeta(top)) { 399 int deref = res.getInt() + 0; 400 ICUResourceBundle ares = top.get(kZONES); res = ares.get(deref); 402 } 403 return res; 404 } 405 411 private static ICUResourceBundle getZoneByName(ICUResourceBundle top, String id) { 412 ICUResourceBundle tmp = top.get(kNAMES); 414 415 int idx = findInStringArray(tmp, id); 417 418 if((idx == -1)) { 419 throw new MissingResourceException (kNAMES, tmp.resPath, id); 421 } else { 424 tmp = top.get(kZONES); tmp = tmp.get(idx); } 427 return tmp; 428 } 429 private static int findInStringArray(ICUResourceBundle array, String id){ 430 int start = 0; 431 int limit = array.getSize(); 432 int mid; 433 String u = null; 434 int lastMid = Integer.MAX_VALUE; 435 if((limit < 1)) { 436 return -1; 437 } 438 for (;;) { 439 mid = (int)((start + limit) / 2); 440 if (lastMid == mid) { 441 break; 442 } 443 lastMid = mid; 444 u = array.getString(mid); 445 if(u==null){ 446 break; 447 } 448 int r = id.compareTo(u); 449 if(r==0) { 450 return mid; 451 } else if(r<0) { 452 limit = mid; 453 } else { 454 start = mid; 455 } 456 } 457 return -1; 458 } 459 private static final String kZONEINFO = "zoneinfo"; 460 private static final String kREGIONS = "Regions"; 461 private static final String kZONES = "Zones"; 462 private static final String kRULES = "Rules"; 463 private static final String kNAMES = "Names"; 464 private static final String kDEFAULT = "Default"; 465 private static final String kGMT_ID = "GMT"; 466 private static final String kCUSTOM_ID= "Custom"; 467 private static java.util.Enumeration idEnum = null; 469 private static SoftCache zoneCache = new SoftCache(); 470 477 static int OLSON_ZONE_START = -1; static int OLSON_ZONE_COUNT = 0; 480 484 private static boolean getOlsonMeta(ICUResourceBundle top) { 485 if (OLSON_ZONE_START < 0) { 486 ICUResourceBundle res = top.get(kZONES); 487 OLSON_ZONE_COUNT = res.getSize(); 488 OLSON_ZONE_START = 0; 489 } 490 return (OLSON_ZONE_START >= 0); 491 } 492 493 496 private static boolean getOlsonMeta() { 497 ICUResourceBundle top = (ICUResourceBundle)ICUResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "zoneinfo", ICUResourceBundle.ICU_DATA_CLASS_LOADER); 498 if(OLSON_ZONE_START < 0) { 499 getOlsonMeta(top); 500 } 501 return (OLSON_ZONE_START >= 0); 502 } 503 508 public static TimeZone getSystemTimeZone(String id) { 509 TimeZone z = (TimeZone)zoneCache.get(id); 510 if (z == null) { 511 try{ 512 ICUResourceBundle top = (ICUResourceBundle)ICUResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "zoneinfo", ICUResourceBundle.ICU_DATA_CLASS_LOADER); 513 ICUResourceBundle res = openOlsonResource(id); 514 z = new OlsonTimeZone(top, res); 515 z.setID(id); 516 zoneCache.put(id, z); 517 }catch(Exception ex){ 518 return null; 519 } 520 } 521 return (TimeZone)z.clone(); 522 } 523 524 public static TimeZone getGMT(){ 525 TimeZone z = new SimpleTimeZone(0, kGMT_ID); 526 z.setID(kGMT_ID); 527 return z; 528 } 529 530 537 public static TimeZone getCustomTimeZone(String id){ 538 539 NumberFormat numberFormat = null; 540 541 String idUppercase = id.toUpperCase(); 542 543 if (id.length() > kGMT_ID.length() && 544 idUppercase.startsWith(kGMT_ID)) 545 { 546 ParsePosition pos = new ParsePosition (kGMT_ID.length()); 547 boolean negative = false; 548 long offset; 549 550 if (id.charAt(pos.getIndex()) == 0x002D ) 551 negative = true; 552 else if (id.charAt(pos.getIndex()) != 0x002B ) 553 return null; 554 pos.setIndex(pos.getIndex() + 1); 555 556 numberFormat = NumberFormat.getInstance(); 557 558 numberFormat.setParseIntegerOnly(true); 559 560 561 int start = pos.getIndex(); 563 564 Number n = numberFormat.parse(id, pos); 565 if (pos.getIndex() == start) { 566 return null; 567 } 568 offset = n.longValue(); 569 570 if (pos.getIndex() < id.length() && 571 id.charAt(pos.getIndex()) == 0x003A ) 572 { 573 offset *= 60; 575 pos.setIndex(pos.getIndex() + 1); 576 int oldPos = pos.getIndex(); 577 n = numberFormat.parse(id, pos); 578 if (pos.getIndex() == oldPos) { 579 return null; 580 } 581 offset += n.longValue(); 582 } 583 else 584 { 585 587 if (offset < 30 && (pos.getIndex() - start) <= 2) 592 offset *= 60; else 594 offset = offset % 100 + offset / 100 * 60; } 596 597 if(negative) 598 offset = -offset; 599 600 TimeZone z = new SimpleTimeZone((int)(offset * 60000), kCUSTOM_ID); 601 z.setID(kCUSTOM_ID); 602 return z; 603 } 604 return null; 605 } 606 } 607 | Popular Tags |