1 7 8 20 21 package java.util; 22 23 import java.io.Serializable ; 24 import java.lang.ref.SoftReference ; 25 import java.security.AccessController ; 26 import java.security.PrivilegedAction ; 27 import java.text.DateFormatSymbols ; 28 import java.util.concurrent.ConcurrentHashMap ; 29 import sun.security.action.GetPropertyAction; 30 import sun.util.calendar.ZoneInfo; 31 import sun.util.calendar.ZoneInfoFile; 32 33 117 abstract public class TimeZone implements Serializable , Cloneable { 118 122 public TimeZone() { 123 } 124 125 131 public static final int SHORT = 0; 132 133 139 public static final int LONG = 1; 140 141 private static final int ONE_MINUTE = 60*1000; 143 private static final int ONE_HOUR = 60*ONE_MINUTE; 144 private static final int ONE_DAY = 24*ONE_HOUR; 145 146 149 private static Hashtable cachedLocaleData = new Hashtable (3); 150 151 static final long serialVersionUID = 3581463369166924961L; 153 154 177 public abstract int getOffset(int era, int year, int month, int day, 178 int dayOfWeek, int milliseconds); 179 180 197 public int getOffset(long date) { 198 if (inDaylightTime(new Date (date))) { 199 return getRawOffset() + getDSTSavings(); 200 } 201 return getRawOffset(); 202 } 203 204 220 int getOffsets(long date, int[] offsets) { 221 int rawoffset = getRawOffset(); 222 int dstoffset = 0; 223 if (inDaylightTime(new Date (date))) { 224 dstoffset = getDSTSavings(); 225 } 226 if (offsets != null) { 227 offsets[0] = rawoffset; 228 offsets[1] = dstoffset; 229 } 230 return rawoffset + dstoffset; 231 } 232 233 245 abstract public void setRawOffset(int offsetMillis); 246 247 263 public abstract int getRawOffset(); 264 265 269 public String getID() 270 { 271 return ID; 272 } 273 274 279 public void setID(String ID) 280 { 281 if (ID == null) { 282 throw new NullPointerException (); 283 } 284 this.ID = ID; 285 } 286 287 297 public final String getDisplayName() { 298 return getDisplayName(false, LONG, Locale.getDefault()); 299 } 300 301 313 public final String getDisplayName(Locale locale) { 314 return getDisplayName(false, LONG, locale); 315 } 316 317 328 public final String getDisplayName(boolean daylight, int style) { 329 return getDisplayName(daylight, style, Locale.getDefault()); 330 } 331 332 346 public String getDisplayName(boolean daylight, int style, Locale locale) { 347 if (style != SHORT && style != LONG) { 348 throw new IllegalArgumentException ("Illegal style: " + style); 349 } 350 351 String id = getID(); 352 String [] names = getDisplayNames(id, locale); 353 if (names == null) { 354 if (id.startsWith("GMT")) { 355 char sign = id.charAt(3); 356 if (sign == '+' || sign == '-') { 357 return id; 358 } 359 } 360 int offset = getRawOffset(); 361 if (daylight) { 362 offset += getDSTSavings(); 363 } 364 return ZoneInfoFile.toCustomID(offset); 365 } 366 367 int index = daylight && useDaylightTime() ? 3 : 1; 368 if (style == SHORT) { 369 index++; 370 } 371 return names[index]; 372 } 373 374 private static class DisplayNames { 375 private static final Map <String , SoftReference <Map <Locale , String []>>> CACHE = 379 new ConcurrentHashMap <String , SoftReference <Map <Locale , String []>>>(); 380 } 381 382 private static final String [] getDisplayNames(String id, Locale locale) { 383 Map <String , SoftReference <Map <Locale , String []>>> displayNames = DisplayNames.CACHE; 384 385 SoftReference <Map <Locale , String []>> ref = displayNames.get(id); 386 if (ref != null) { 387 Map <Locale , String []> perLocale = ref.get(); 388 if (perLocale != null) { 389 String [] names = perLocale.get(locale); 390 if (names != null) { 391 return names; 392 } 393 names = retrieveDisplayNames(id, locale); 394 if (names != null) { 395 perLocale.put(locale, names); 396 } 397 return names; 398 } 399 } 400 401 String [] names = retrieveDisplayNames(id, locale); 402 if (names != null) { 403 Map <Locale , String []> perLocale = new ConcurrentHashMap <Locale , String []>(); 404 perLocale.put(locale, names); 405 ref = new SoftReference <Map <Locale , String []>>(perLocale); 406 displayNames.put(id, ref); 407 } 408 return names; 409 } 410 411 private static final String [] retrieveDisplayNames(String id, Locale locale) { 412 String [][] tznames = new DateFormatSymbols (locale).getZoneStrings(); 413 for (int i = 0; i < tznames.length; i++) { 414 String [] names = tznames[i]; 415 if (id.equals(names[0])) { 416 return names; 417 } 418 } 419 return null; 420 } 421 422 437 public int getDSTSavings() { 438 if (useDaylightTime()) { 439 return 3600000; 440 } 441 return 0; 442 } 443 444 455 public abstract boolean useDaylightTime(); 456 457 464 abstract public boolean inDaylightTime(Date date); 465 466 477 public static synchronized TimeZone getTimeZone(String ID) { 478 return getTimeZone(ID, true); 479 } 480 481 private static TimeZone getTimeZone(String ID, boolean fallback) { 482 TimeZone tz = ZoneInfo.getTimeZone(ID); 483 if (tz == null) { 484 tz = parseCustomTimeZone(ID); 485 if (tz == null && fallback) { 486 tz = new ZoneInfo(GMT_ID, 0); 487 } 488 } 489 return tz; 490 } 491 492 499 public static synchronized String [] getAvailableIDs(int rawOffset) { 500 return ZoneInfo.getAvailableIDs(rawOffset); 501 } 502 503 507 public static synchronized String [] getAvailableIDs() { 508 return ZoneInfo.getAvailableIDs(); 509 } 510 511 514 private static native String getSystemTimeZoneID(String javaHome, 515 String country); 516 517 521 private static native String getSystemGMTOffsetID(); 522 523 530 public static TimeZone getDefault() { 531 return (TimeZone ) getDefaultRef().clone(); 532 } 533 534 538 static TimeZone getDefaultRef() { 539 TimeZone defaultZone = defaultZoneTL.get(); 540 if (defaultZone == null) { 541 defaultZone = defaultTimeZone; 542 if (defaultZone == null) { 543 defaultZone = setDefaultZone(); 545 assert defaultZone != null; 546 } 547 } 548 return defaultZone; 550 } 551 552 private static synchronized TimeZone setDefaultZone() { 553 TimeZone tz = null; 554 String zoneID = (String ) AccessController.doPrivileged( 556 new GetPropertyAction("user.timezone")); 557 558 if (zoneID == null || zoneID.equals("")) { 561 String country = (String ) AccessController.doPrivileged( 562 new GetPropertyAction("user.country")); 563 String javaHome = (String ) AccessController.doPrivileged( 564 new GetPropertyAction("java.home")); 565 try { 566 zoneID = getSystemTimeZoneID(javaHome, country); 567 if (zoneID == null) { 568 zoneID = GMT_ID; 569 } 570 } catch (NullPointerException e) { 571 zoneID = GMT_ID; 572 } 573 } 574 575 tz = getTimeZone(zoneID, false); 578 579 if (tz == null) { 580 String gmtOffsetID = getSystemGMTOffsetID(); 584 if (gmtOffsetID != null) { 585 zoneID = gmtOffsetID; 586 } 587 tz = getTimeZone(zoneID, true); 588 } 589 assert tz != null; 590 591 final String id = zoneID; 592 AccessController.doPrivileged(new PrivilegedAction <Object >() { 593 public Object run() { 594 System.setProperty("user.timezone", id); 595 return null; 596 } 597 }); 598 599 if (hasPermission()) { 600 defaultTimeZone = tz; 601 } else { 602 defaultZoneTL.set(tz); 603 } 604 return tz; 605 } 606 607 private static boolean hasPermission() { 608 boolean hasPermission = true; 609 SecurityManager sm = System.getSecurityManager(); 610 if (sm != null) { 611 try { 612 sm.checkPermission(new PropertyPermission 613 ("user.timezone", "write")); 614 } catch (SecurityException e) { 615 hasPermission = false; 616 } 617 } 618 return hasPermission; 619 } 620 621 629 public static void setDefault(TimeZone zone) { 630 if (hasPermission()) { 631 synchronized (TimeZone .class) { 632 defaultTimeZone = zone; 633 } 634 } else { 635 defaultZoneTL.set(zone); 636 } 637 } 638 639 648 public boolean hasSameRules(TimeZone other) { 649 return other != null && getRawOffset() == other.getRawOffset() && 650 useDaylightTime() == other.useDaylightTime(); 651 } 652 653 658 public Object clone() 659 { 660 try { 661 TimeZone other = (TimeZone ) super.clone(); 662 other.ID = ID; 663 return other; 664 } catch (CloneNotSupportedException e) { 665 throw new InternalError (); 666 } 667 } 668 669 672 static final TimeZone NO_TIMEZONE = null; 673 674 676 684 private String ID; 685 private static volatile TimeZone defaultTimeZone; 686 private static final InheritableThreadLocal <TimeZone > defaultZoneTL 687 = new InheritableThreadLocal <TimeZone >(); 688 689 static final String GMT_ID = "GMT"; 690 private static final int GMT_ID_LENGTH = 3; 691 692 700 private static final TimeZone parseCustomTimeZone(String id) { 701 int length; 702 703 if ((length = id.length()) < (GMT_ID_LENGTH + 2) || 706 id.indexOf(GMT_ID) != 0) { 707 return null; 708 } 709 710 ZoneInfo zi; 711 712 zi = ZoneInfoFile.getZoneInfo(id); 716 if (zi != null) { 717 return zi; 718 } 719 720 int index = GMT_ID_LENGTH; 721 boolean negative = false; 722 char c = id.charAt(index++); 723 if (c == '-') { 724 negative = true; 725 } else if (c != '+') { 726 return null; 727 } 728 729 int hours = 0; 730 int num = 0; 731 int countDelim = 0; 732 int len = 0; 733 while (index < length) { 734 c = id.charAt(index++); 735 if (c == ':') { 736 if (countDelim > 0) { 737 return null; 738 } 739 if (len > 2) { 740 return null; 741 } 742 hours = num; 743 countDelim++; 744 num = 0; 745 len = 0; 746 continue; 747 } 748 if (c < '0' || c > '9') { 749 return null; 750 } 751 num = num * 10 + (c - '0'); 752 len++; 753 } 754 if (index != length) { 755 return null; 756 } 757 if (countDelim == 0) { 758 if (len <= 2) { 759 hours = num; 760 num = 0; 761 } else { 762 hours = num / 100; 763 num %= 100; 764 } 765 } else { 766 if (len != 2) { 767 return null; 768 } 769 } 770 if (hours > 23 || num > 59) { 771 return null; 772 } 773 int gmtOffset = (hours * 60 + num) * 60 * 1000; 774 775 if (gmtOffset == 0) { 776 zi = ZoneInfoFile.getZoneInfo(GMT_ID); 777 if (negative) { 778 zi.setID("GMT-00:00"); 779 } else { 780 zi.setID("GMT+00:00"); 781 } 782 } else { 783 zi = ZoneInfoFile.getCustomTimeZone(id, negative ? -gmtOffset : gmtOffset); 784 } 785 return zi; 786 } 787 } 788 | Popular Tags |