2 *******************************************************************************
3 * Copyright (C) 2008-2013, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
7 package com.ibm.icu.impl.icuadapter;
9 import java.lang.reflect.InvocationTargetException;
10 import java.lang.reflect.Method;
11 import java.util.Calendar;
12 import java.util.Date;
13 import java.util.GregorianCalendar;
14 import java.util.Locale;
15 import java.util.TimeZone;
17 import com.ibm.icu.impl.Grego;
18 import com.ibm.icu.impl.jdkadapter.TimeZoneICU;
19 import com.ibm.icu.util.ULocale;
22 * TimeZoneJDK is an adapter class which wraps java.util.TimeZone and
23 * implements ICU4J TimeZone APIs.
25 public class TimeZoneJDK extends com.ibm.icu.util.TimeZone {
27 private static final long serialVersionUID = -1137052823551791933L;
29 private TimeZone fJdkTz;
30 private transient Calendar fJdkCal;
31 private static Method mObservesDaylightTime;
35 mObservesDaylightTime = TimeZone.class.getMethod("observesDaylightTime", (Class[]) null);
36 } catch (NoSuchMethodException e) {
38 } catch (SecurityException e) {
43 private TimeZoneJDK(TimeZone jdkTz) {
44 fJdkTz = (TimeZone)jdkTz.clone();
47 public static com.ibm.icu.util.TimeZone wrap(TimeZone jdkTz) {
48 if (jdkTz instanceof TimeZoneICU) {
49 return ((TimeZoneICU)jdkTz).unwrap();
51 return new TimeZoneJDK(jdkTz);
54 public TimeZone unwrap() {
55 return (TimeZone)fJdkTz.clone();
59 public Object clone() {
63 return cloneAsThawed();
67 public boolean equals(Object obj) {
68 if (obj instanceof TimeZoneJDK) {
69 return (((TimeZoneJDK)obj).fJdkTz).equals(fJdkTz);
74 //public String getDisplayName()
75 //public String getDisplayName(boolean daylight, int style)
76 //public String getDisplayName(Locale locale)
77 //public String getDisplayName(ULocale locale)
79 public String getDisplayName(boolean daylight, int style, Locale locale) {
80 return fJdkTz.getDisplayName(daylight, style, locale);
84 public String getDisplayName(boolean daylight, int style, ULocale locale) {
85 return fJdkTz.getDisplayName(daylight, style, locale.toLocale());
89 public int getDSTSavings() {
90 return fJdkTz.getDSTSavings();
94 public String getID() {
95 return fJdkTz.getID();
99 public int getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds) {
100 return fJdkTz.getOffset(era, year, month, day, dayOfWeek, milliseconds);
104 public int getOffset(long date) {
105 return fJdkTz.getOffset(date);
109 public void getOffset(long date, boolean local, int[] offsets) {
111 if (fJdkCal == null) {
112 fJdkCal = new GregorianCalendar(fJdkTz);
115 int fields[] = new int[6];
116 Grego.timeToFields(date, fields);
117 int hour, min, sec, mil;
126 fJdkCal.set(fields[0], fields[1], fields[2], hour, min, sec);
127 fJdkCal.set(java.util.Calendar.MILLISECOND, mil);
129 int doy1, hour1, min1, sec1, mil1;
130 doy1 = fJdkCal.get(java.util.Calendar.DAY_OF_YEAR);
131 hour1 = fJdkCal.get(java.util.Calendar.HOUR_OF_DAY);
132 min1 = fJdkCal.get(java.util.Calendar.MINUTE);
133 sec1 = fJdkCal.get(java.util.Calendar.SECOND);
134 mil1 = fJdkCal.get(java.util.Calendar.MILLISECOND);
136 if (fields[4] != doy1 || hour != hour1 || min != min1 || sec != sec1 || mil != mil1) {
137 // Calendar field(s) were changed due to the adjustment for non-existing time
138 // Note: This code does not support non-existing local time at year boundary properly.
139 // But, it should work fine for real timezones.
140 int dayDelta = Math.abs(doy1 - fields[4]) > 1 ? 1 : doy1 - fields[4];
141 int delta = ((((dayDelta * 24) + hour1 - hour) * 60 + min1 - min) * 60 + sec1 - sec) * 1000 + mil1 - mil;
143 // In this case, we use the offsets before the transition
144 fJdkCal.setTimeInMillis(fJdkCal.getTimeInMillis() - delta - 1);
147 fJdkCal.setTimeInMillis(date);
149 offsets[0] = fJdkCal.get(java.util.Calendar.ZONE_OFFSET);
150 offsets[1] = fJdkCal.get(java.util.Calendar.DST_OFFSET);
155 public int getRawOffset() {
156 return fJdkTz.getRawOffset();
160 public int hashCode() {
161 return fJdkTz.hashCode();
165 public boolean hasSameRules(com.ibm.icu.util.TimeZone other) {
166 return other.hasSameRules(TimeZoneJDK.wrap(fJdkTz));
170 public boolean inDaylightTime(Date date) {
171 return fJdkTz.inDaylightTime(date);
175 public void setID(String ID) {
177 throw new UnsupportedOperationException("Attempt to modify a frozen TimeZoneJDK instance.");
183 public void setRawOffset(int offsetMillis) {
185 throw new UnsupportedOperationException("Attempt to modify a frozen TimeZoneJDK instance.");
187 fJdkTz.setRawOffset(offsetMillis);
191 public boolean useDaylightTime() {
192 return fJdkTz.useDaylightTime();
196 public boolean observesDaylightTime() {
197 if (mObservesDaylightTime != null) {
200 return (Boolean)mObservesDaylightTime.invoke(fJdkTz, (Object[]) null);
201 } catch (IllegalAccessException e) {
202 } catch (IllegalArgumentException e) {
203 } catch (InvocationTargetException e) {
206 return super.observesDaylightTime();
210 private transient boolean fIsFrozen = false;
213 public boolean isFrozen() {
218 public com.ibm.icu.util.TimeZone freeze() {
224 public com.ibm.icu.util.TimeZone cloneAsThawed() {
225 TimeZoneJDK tz = (TimeZoneJDK)super.cloneAsThawed();
226 tz.fJdkTz = (TimeZone)fJdkTz.clone();
227 tz.fJdkCal = null; // To be instantiated when necessary
228 tz.fIsFrozen = false;