< prev index next >
src/java.base/share/classes/java/util/TimeZone.java
Print this page
@@ -291,10 +291,11 @@
{
if (ID == null) {
throw new NullPointerException();
}
this.ID = ID;
+ this.zoneId = null; // invalidate cache
}
/**
* Returns a long standard time name of this {@code TimeZone} suitable for
* presentation to the user in the default locale.
@@ -542,11 +543,27 @@
* @return a {@code ZoneId} representing the same time zone as this
* {@code TimeZone}
* @since 1.8
*/
public ZoneId toZoneId() {
+ ZoneId zId = zoneId;
+ if (zId == null) {
+ zoneId = zId = toZoneId0();
+ }
+ return zId;
+ }
+
+ private ZoneId toZoneId0() {
String id = getID();
+ TimeZone defaultZone = defaultTimeZone;
+ // are we not defaultTimeZone but our id is equal to default's?
+ if (defaultZone != this &&
+ defaultZone != null && id.equals(defaultZone.getID())) {
+ // delegate to default TZ which is effectively immutable
+ return defaultZone.toZoneId();
+ }
+ // derive it ourselves
if (ZoneInfoFile.useOldMapping() && id.length() == 3) {
if ("EST".equals(id))
return ZoneId.of("America/New_York");
if ("MST".equals(id))
return ZoneId.of("America/Denver");
@@ -708,11 +725,16 @@
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new PropertyPermission
("user.timezone", "write"));
}
- defaultTimeZone = zone;
+ // by saving a defensive clone and returning a clone in getDefault() too,
+ // the defaultTimeZone instance is isolated from user code which makes it
+ // effectively immutable. This is important to avoid races when the
+ // following is evaluated in ZoneId.systemDefault():
+ // TimeZone.getDefault().toZoneId().
+ defaultTimeZone = (zone == null) ? null : (TimeZone) zone.clone();
}
/**
* Returns true if this zone has the same rule and offset as another zone.
* That is, if this zone differs only in ID, if at all. Returns false
@@ -733,13 +755,11 @@
* @return a clone of this <code>TimeZone</code>
*/
public Object clone()
{
try {
- TimeZone other = (TimeZone) super.clone();
- other.ID = ID;
- return other;
+ return super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
@@ -757,10 +777,16 @@
* display names. <code>ID</code> values are unique in the system
* table but may not be for dynamically created zones.
* @serial
*/
private String ID;
+
+ /**
+ * Cached {@link ZoneId} for this TimeZone
+ */
+ private transient ZoneId zoneId;
+
private static volatile TimeZone defaultTimeZone;
static final String GMT_ID = "GMT";
private static final int GMT_ID_LENGTH = 3;
< prev index next >