25
26 /*
27 * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
28 * (C) Copyright IBM Corp. 1996 - All Rights Reserved
29 *
30 * The original version of this source code and documentation is copyrighted
31 * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
32 * materials are provided under terms of a License Agreement between Taligent
33 * and Sun. This technology is protected by multiple US and International
34 * patents. This notice and attribution to Taligent may not be removed.
35 * Taligent is a registered trademark of Taligent, Inc.
36 *
37 */
38
39 package java.util;
40
41 import java.io.Serializable;
42 import java.security.AccessController;
43 import java.security.PrivilegedAction;
44 import java.time.ZoneId;
45 import sun.security.action.GetPropertyAction;
46 import sun.util.calendar.ZoneInfo;
47 import sun.util.calendar.ZoneInfoFile;
48 import sun.util.locale.provider.TimeZoneNameUtility;
49
50 /**
51 * <code>TimeZone</code> represents a time zone offset, and also figures out daylight
52 * savings.
53 *
54 * <p>
55 * Typically, you get a <code>TimeZone</code> using <code>getDefault</code>
56 * which creates a <code>TimeZone</code> based on the time zone where the program
57 * is running. For example, for a program running in Japan, <code>getDefault</code>
58 * creates a <code>TimeZone</code> object based on Japanese Standard Time.
59 *
60 * <p>
61 * You can also get a <code>TimeZone</code> using <code>getTimeZone</code>
62 * along with a time zone ID. For instance, the time zone ID for the
63 * U.S. Pacific Time zone is "America/Los_Angeles". So, you can get a
64 * U.S. Pacific Time <code>TimeZone</code> object with:
114 * </pre></blockquote>
115 * For example, TimeZone.getTimeZone("GMT-8").getID() returns "GMT-08:00".
116 *
117 * <h3>Three-letter time zone IDs</h3>
118 *
119 * For compatibility with JDK 1.1.x, some other three-letter time zone IDs
120 * (such as "PST", "CTT", "AST") are also supported. However, <strong>their
121 * use is deprecated</strong> because the same abbreviation is often used
122 * for multiple time zones (for example, "CST" could be U.S. "Central Standard
123 * Time" and "China Standard Time"), and the Java platform can then only
124 * recognize one of them.
125 *
126 *
127 * @see Calendar
128 * @see GregorianCalendar
129 * @see SimpleTimeZone
130 * @author Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu
131 * @since 1.1
132 */
133 abstract public class TimeZone implements Serializable, Cloneable {
134 /**
135 * Sole constructor. (For invocation by subclass constructors, typically
136 * implicit.)
137 */
138 public TimeZone() {
139 }
140
141 /**
142 * A style specifier for <code>getDisplayName()</code> indicating
143 * a short name, such as "PST."
144 * @see #LONG
145 * @since 1.2
146 */
147 public static final int SHORT = 0;
148
149 /**
150 * A style specifier for <code>getDisplayName()</code> indicating
151 * a long name, such as "Pacific Standard Time."
152 * @see #SHORT
153 * @since 1.2
276 /**
277 * Gets the ID of this time zone.
278 * @return the ID of this time zone.
279 */
280 public String getID()
281 {
282 return ID;
283 }
284
285 /**
286 * Sets the time zone ID. This does not change any other data in
287 * the time zone object.
288 * @param ID the new time zone ID.
289 */
290 public void setID(String ID)
291 {
292 if (ID == null) {
293 throw new NullPointerException();
294 }
295 this.ID = ID;
296 }
297
298 /**
299 * Returns a long standard time name of this {@code TimeZone} suitable for
300 * presentation to the user in the default locale.
301 *
302 * <p>This method is equivalent to:
303 * <blockquote><pre>
304 * getDisplayName(false, {@link #LONG},
305 * Locale.getDefault({@link Locale.Category#DISPLAY}))
306 * </pre></blockquote>
307 *
308 * @return the human-readable name of this time zone in the default locale.
309 * @since 1.2
310 * @see #getDisplayName(boolean, int, Locale)
311 * @see Locale#getDefault(Locale.Category)
312 * @see Locale.Category
313 */
314 public final String getDisplayName() {
315 return getDisplayName(false, LONG,
527 */
528 public static TimeZone getTimeZone(ZoneId zoneId) {
529 String tzid = zoneId.getId(); // throws an NPE if null
530 char c = tzid.charAt(0);
531 if (c == '+' || c == '-') {
532 tzid = "GMT" + tzid;
533 } else if (c == 'Z' && tzid.length() == 1) {
534 tzid = "UTC";
535 }
536 return getTimeZone(tzid, true);
537 }
538
539 /**
540 * Converts this {@code TimeZone} object to a {@code ZoneId}.
541 *
542 * @return a {@code ZoneId} representing the same time zone as this
543 * {@code TimeZone}
544 * @since 1.8
545 */
546 public ZoneId toZoneId() {
547 String id = getID();
548 if (ZoneInfoFile.useOldMapping() && id.length() == 3) {
549 if ("EST".equals(id))
550 return ZoneId.of("America/New_York");
551 if ("MST".equals(id))
552 return ZoneId.of("America/Denver");
553 if ("HST".equals(id))
554 return ZoneId.of("America/Honolulu");
555 }
556 return ZoneId.of(id, ZoneId.SHORT_IDS);
557 }
558
559 private static TimeZone getTimeZone(String ID, boolean fallback) {
560 TimeZone tz = ZoneInfo.getTimeZone(ID);
561 if (tz == null) {
562 tz = parseCustomTimeZone(ID);
563 if (tz == null && fallback) {
564 tz = new ZoneInfo(GMT_ID, 0);
565 }
566 }
567 return tz;
568 }
569
570 /**
571 * Gets the available IDs according to the given time zone offset in milliseconds.
572 *
573 * @param rawOffset the given time zone GMT offset in milliseconds.
574 * @return an array of IDs, where the time zone for that ID has
575 * the specified GMT offset. For example, "America/Phoenix" and "America/Denver"
576 * both have GMT-07:00, but differ in daylight saving behavior.
693 /**
694 * Sets the {@code TimeZone} that is returned by the {@code getDefault}
695 * method. {@code zone} is cached. If {@code zone} is null, the cached
696 * default {@code TimeZone} is cleared. This method doesn't change the value
697 * of the {@code user.timezone} property.
698 *
699 * @param zone the new default {@code TimeZone}, or null
700 * @throws SecurityException if the security manager's {@code checkPermission}
701 * denies {@code PropertyPermission("user.timezone",
702 * "write")}
703 * @see #getDefault
704 * @see PropertyPermission
705 */
706 public static void setDefault(TimeZone zone)
707 {
708 SecurityManager sm = System.getSecurityManager();
709 if (sm != null) {
710 sm.checkPermission(new PropertyPermission
711 ("user.timezone", "write"));
712 }
713 defaultTimeZone = zone;
714 }
715
716 /**
717 * Returns true if this zone has the same rule and offset as another zone.
718 * That is, if this zone differs only in ID, if at all. Returns false
719 * if the other zone is null.
720 * @param other the <code>TimeZone</code> object to be compared with
721 * @return true if the other zone is not null and is the same as this one,
722 * with the possible exception of the ID
723 * @since 1.2
724 */
725 public boolean hasSameRules(TimeZone other) {
726 return other != null && getRawOffset() == other.getRawOffset() &&
727 useDaylightTime() == other.useDaylightTime();
728 }
729
730 /**
731 * Creates a copy of this <code>TimeZone</code>.
732 *
733 * @return a clone of this <code>TimeZone</code>
734 */
735 public Object clone()
736 {
737 try {
738 TimeZone other = (TimeZone) super.clone();
739 other.ID = ID;
740 return other;
741 } catch (CloneNotSupportedException e) {
742 throw new InternalError(e);
743 }
744 }
745
746 /**
747 * The null constant as a TimeZone.
748 */
749 static final TimeZone NO_TIMEZONE = null;
750
751 // =======================privates===============================
752
753 /**
754 * The string identifier of this <code>TimeZone</code>. This is a
755 * programmatic identifier used internally to look up <code>TimeZone</code>
756 * objects from the system table and also to map them to their localized
757 * display names. <code>ID</code> values are unique in the system
758 * table but may not be for dynamically created zones.
759 * @serial
760 */
761 private String ID;
762 private static volatile TimeZone defaultTimeZone;
763
764 static final String GMT_ID = "GMT";
765 private static final int GMT_ID_LENGTH = 3;
766
767 // a static TimeZone we can reference if no AppContext is in place
768 private static volatile TimeZone mainAppContextDefault;
769
770 /**
771 * Parses a custom time zone identifier and returns a corresponding zone.
772 * This method doesn't support the RFC 822 time zone format. (e.g., +hhmm)
773 *
774 * @param id a string of the <a href="#CustomID">custom ID form</a>.
775 * @return a newly created TimeZone with the given offset and
776 * no daylight saving time, or null if the id cannot be parsed.
777 */
778 private static final TimeZone parseCustomTimeZone(String id) {
779 int length;
780
781 // Error if the length of id isn't long enough or id doesn't
|
25
26 /*
27 * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
28 * (C) Copyright IBM Corp. 1996 - All Rights Reserved
29 *
30 * The original version of this source code and documentation is copyrighted
31 * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
32 * materials are provided under terms of a License Agreement between Taligent
33 * and Sun. This technology is protected by multiple US and International
34 * patents. This notice and attribution to Taligent may not be removed.
35 * Taligent is a registered trademark of Taligent, Inc.
36 *
37 */
38
39 package java.util;
40
41 import java.io.Serializable;
42 import java.security.AccessController;
43 import java.security.PrivilegedAction;
44 import java.time.ZoneId;
45
46 import sun.misc.JavaUtilTimeZoneAccess;
47 import sun.misc.SharedSecrets;
48 import sun.security.action.GetPropertyAction;
49 import sun.util.calendar.ZoneInfo;
50 import sun.util.calendar.ZoneInfoFile;
51 import sun.util.locale.provider.TimeZoneNameUtility;
52
53 /**
54 * <code>TimeZone</code> represents a time zone offset, and also figures out daylight
55 * savings.
56 *
57 * <p>
58 * Typically, you get a <code>TimeZone</code> using <code>getDefault</code>
59 * which creates a <code>TimeZone</code> based on the time zone where the program
60 * is running. For example, for a program running in Japan, <code>getDefault</code>
61 * creates a <code>TimeZone</code> object based on Japanese Standard Time.
62 *
63 * <p>
64 * You can also get a <code>TimeZone</code> using <code>getTimeZone</code>
65 * along with a time zone ID. For instance, the time zone ID for the
66 * U.S. Pacific Time zone is "America/Los_Angeles". So, you can get a
67 * U.S. Pacific Time <code>TimeZone</code> object with:
117 * </pre></blockquote>
118 * For example, TimeZone.getTimeZone("GMT-8").getID() returns "GMT-08:00".
119 *
120 * <h3>Three-letter time zone IDs</h3>
121 *
122 * For compatibility with JDK 1.1.x, some other three-letter time zone IDs
123 * (such as "PST", "CTT", "AST") are also supported. However, <strong>their
124 * use is deprecated</strong> because the same abbreviation is often used
125 * for multiple time zones (for example, "CST" could be U.S. "Central Standard
126 * Time" and "China Standard Time"), and the Java platform can then only
127 * recognize one of them.
128 *
129 *
130 * @see Calendar
131 * @see GregorianCalendar
132 * @see SimpleTimeZone
133 * @author Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu
134 * @since 1.1
135 */
136 abstract public class TimeZone implements Serializable, Cloneable {
137
138 static {
139 SharedSecrets.setJavaUtilTimeZoneAccess(new JavaUtilTimeZoneAccess() {
140 @Override
141 public TimeZone getDefaultRef() {
142 return TimeZone.getDefaultRef();
143 }
144 });
145 }
146
147 /**
148 * Sole constructor. (For invocation by subclass constructors, typically
149 * implicit.)
150 */
151 public TimeZone() {
152 }
153
154 /**
155 * A style specifier for <code>getDisplayName()</code> indicating
156 * a short name, such as "PST."
157 * @see #LONG
158 * @since 1.2
159 */
160 public static final int SHORT = 0;
161
162 /**
163 * A style specifier for <code>getDisplayName()</code> indicating
164 * a long name, such as "Pacific Standard Time."
165 * @see #SHORT
166 * @since 1.2
289 /**
290 * Gets the ID of this time zone.
291 * @return the ID of this time zone.
292 */
293 public String getID()
294 {
295 return ID;
296 }
297
298 /**
299 * Sets the time zone ID. This does not change any other data in
300 * the time zone object.
301 * @param ID the new time zone ID.
302 */
303 public void setID(String ID)
304 {
305 if (ID == null) {
306 throw new NullPointerException();
307 }
308 this.ID = ID;
309 this.zoneId = null; // invalidate cache
310 }
311
312 /**
313 * Returns a long standard time name of this {@code TimeZone} suitable for
314 * presentation to the user in the default locale.
315 *
316 * <p>This method is equivalent to:
317 * <blockquote><pre>
318 * getDisplayName(false, {@link #LONG},
319 * Locale.getDefault({@link Locale.Category#DISPLAY}))
320 * </pre></blockquote>
321 *
322 * @return the human-readable name of this time zone in the default locale.
323 * @since 1.2
324 * @see #getDisplayName(boolean, int, Locale)
325 * @see Locale#getDefault(Locale.Category)
326 * @see Locale.Category
327 */
328 public final String getDisplayName() {
329 return getDisplayName(false, LONG,
541 */
542 public static TimeZone getTimeZone(ZoneId zoneId) {
543 String tzid = zoneId.getId(); // throws an NPE if null
544 char c = tzid.charAt(0);
545 if (c == '+' || c == '-') {
546 tzid = "GMT" + tzid;
547 } else if (c == 'Z' && tzid.length() == 1) {
548 tzid = "UTC";
549 }
550 return getTimeZone(tzid, true);
551 }
552
553 /**
554 * Converts this {@code TimeZone} object to a {@code ZoneId}.
555 *
556 * @return a {@code ZoneId} representing the same time zone as this
557 * {@code TimeZone}
558 * @since 1.8
559 */
560 public ZoneId toZoneId() {
561 ZoneId zId = zoneId;
562 if (zId == null) {
563 String id = getID();
564 if (ZoneInfoFile.useOldMapping() && id.length() == 3) {
565 if ("EST".equals(id))
566 zId = ZoneId.of("America/New_York");
567 else if ("MST".equals(id))
568 zId = ZoneId.of("America/Denver");
569 else if ("HST".equals(id))
570 zId = ZoneId.of("America/Honolulu");
571 } else {
572 zId = ZoneId.of(id, ZoneId.SHORT_IDS);
573 }
574 zoneId = zId;
575 }
576 return zId;
577 }
578
579 private static TimeZone getTimeZone(String ID, boolean fallback) {
580 TimeZone tz = ZoneInfo.getTimeZone(ID);
581 if (tz == null) {
582 tz = parseCustomTimeZone(ID);
583 if (tz == null && fallback) {
584 tz = new ZoneInfo(GMT_ID, 0);
585 }
586 }
587 return tz;
588 }
589
590 /**
591 * Gets the available IDs according to the given time zone offset in milliseconds.
592 *
593 * @param rawOffset the given time zone GMT offset in milliseconds.
594 * @return an array of IDs, where the time zone for that ID has
595 * the specified GMT offset. For example, "America/Phoenix" and "America/Denver"
596 * both have GMT-07:00, but differ in daylight saving behavior.
713 /**
714 * Sets the {@code TimeZone} that is returned by the {@code getDefault}
715 * method. {@code zone} is cached. If {@code zone} is null, the cached
716 * default {@code TimeZone} is cleared. This method doesn't change the value
717 * of the {@code user.timezone} property.
718 *
719 * @param zone the new default {@code TimeZone}, or null
720 * @throws SecurityException if the security manager's {@code checkPermission}
721 * denies {@code PropertyPermission("user.timezone",
722 * "write")}
723 * @see #getDefault
724 * @see PropertyPermission
725 */
726 public static void setDefault(TimeZone zone)
727 {
728 SecurityManager sm = System.getSecurityManager();
729 if (sm != null) {
730 sm.checkPermission(new PropertyPermission
731 ("user.timezone", "write"));
732 }
733 defaultTimeZone = (TimeZone) zone.clone();
734 }
735
736 /**
737 * Returns true if this zone has the same rule and offset as another zone.
738 * That is, if this zone differs only in ID, if at all. Returns false
739 * if the other zone is null.
740 * @param other the <code>TimeZone</code> object to be compared with
741 * @return true if the other zone is not null and is the same as this one,
742 * with the possible exception of the ID
743 * @since 1.2
744 */
745 public boolean hasSameRules(TimeZone other) {
746 return other != null && getRawOffset() == other.getRawOffset() &&
747 useDaylightTime() == other.useDaylightTime();
748 }
749
750 /**
751 * Creates a copy of this <code>TimeZone</code>.
752 *
753 * @return a clone of this <code>TimeZone</code>
754 */
755 public Object clone()
756 {
757 try {
758 return super.clone();
759 } catch (CloneNotSupportedException e) {
760 throw new InternalError(e);
761 }
762 }
763
764 /**
765 * The null constant as a TimeZone.
766 */
767 static final TimeZone NO_TIMEZONE = null;
768
769 // =======================privates===============================
770
771 /**
772 * The string identifier of this <code>TimeZone</code>. This is a
773 * programmatic identifier used internally to look up <code>TimeZone</code>
774 * objects from the system table and also to map them to their localized
775 * display names. <code>ID</code> values are unique in the system
776 * table but may not be for dynamically created zones.
777 * @serial
778 */
779 private String ID;
780
781 /**
782 * Cached {@link ZoneId} for this TimeZone
783 */
784 private transient ZoneId zoneId;
785
786 private static volatile TimeZone defaultTimeZone;
787
788 static final String GMT_ID = "GMT";
789 private static final int GMT_ID_LENGTH = 3;
790
791 // a static TimeZone we can reference if no AppContext is in place
792 private static volatile TimeZone mainAppContextDefault;
793
794 /**
795 * Parses a custom time zone identifier and returns a corresponding zone.
796 * This method doesn't support the RFC 822 time zone format. (e.g., +hhmm)
797 *
798 * @param id a string of the <a href="#CustomID">custom ID form</a>.
799 * @return a newly created TimeZone with the given offset and
800 * no daylight saving time, or null if the id cannot be parsed.
801 */
802 private static final TimeZone parseCustomTimeZone(String id) {
803 int length;
804
805 // Error if the length of id isn't long enough or id doesn't
|