ICU-9354 Partially backported JDK TimeZone support (#5975) to eclipse-34 stream to reduce the tzdata maintenance work load.
X-SVN-Rev: 31885
diff --git a/.gitattributes b/.gitattributes
index 66848fa..e301184 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -55,6 +55,7 @@
eclipseProjectMisc/normSrc.launch -text
/ee.foundation.jar -text
/preprocessor.txt -text
+src/com/ibm/icu/ICUConfig.properties -text
src/com/ibm/icu/dev/data/rbbi/english.dict -text
src/com/ibm/icu/dev/data/testdata.jar -text
src/com/ibm/icu/dev/data/thai6.ucs -text
diff --git a/build.properties b/build.properties
index d187470..6156152 100644
--- a/build.properties
+++ b/build.properties
@@ -29,4 +29,4 @@
icu4j.plugin.impl.version.string=3.8.1
copyright.eclipse=Licensed Materials - Property of IBM \n (C) Copyright IBM Corp. 2000, 2012. All Rights Reserved. \n IBM is a registered trademark of IBM Corp.
-icu4j.eclipse.build.version.string=3.8.1.v20120406
\ No newline at end of file
+icu4j.eclipse.build.version.string=3.8.1.v20120530
\ No newline at end of file
diff --git a/build.xml b/build.xml
index 7f3dae5..2fbdc20 100644
--- a/build.xml
+++ b/build.xml
@@ -1,7 +1,7 @@
<!--
/*
*******************************************************************************
-* Copyright (C) 1997-2009, International Business Machines Corporation and *
+* Copyright (C) 1997-2012, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
* This is the ant build file for ICU4J. See readme.html for more information.
@@ -287,6 +287,7 @@
<copy todir="${build.dir}/META-INF">
<fileset dir="${src.dir}/META-INF" includes="**/*" />
</copy>
+ <copy file="${src.dir}/com/ibm/icu/ICUConfig.properties" todir="${build.dir}/com/ibm/icu"/>
</target>
<target name="durationdata" depends="initBase">
@@ -1661,6 +1662,7 @@
<include name="com/ibm/icu/math/**/*" />
<include name="com/ibm/icu/impl/**/*" />
<include name="com/ibm/icu/lang/**/*" />
+ <include name="com/ibm/icu/ICUConfig.properties" />
</fileset>
<manifest>
<attribute name="Built-By" value="${corp}" />
@@ -1691,7 +1693,7 @@
<!-- icu source -->
<copy toDir="${eclipse.projects.dir}/plugins/com.ibm.icu/src/com/ibm/icu">
<fileset dir="src/com/ibm/icu"
- includes="impl/**/*,lang/**/*,math/**/*,text/**/*,util/**/*"
+ includes="impl/**/*,lang/**/*,math/**/*,text/**/*,util/**/*,ICUConfig.properties"
excludes="**/.svn/**/*,**/*.jar,**/Transliterator_Han_Latin*.txt" />
</copy>
<!-- icu data -->
diff --git a/preprocessor.txt b/preprocessor.txt
index 6118635..882702d 100644
--- a/preprocessor.txt
+++ b/preprocessor.txt
@@ -1,4 +1,4 @@
-# Copyright (C) 2007, International Business Machines Corporation and
+# Copyright (C) 2007-2012, International Business Machines Corporation and
# others. All Rights Reserved.
## core sources
@@ -7,6 +7,7 @@
src/com/ibm/icu/impl/duration/BasicDurationFormat.java
src/com/ibm/icu/impl/ICUResourceBundleImpl.java
src/com/ibm/icu/impl/ICUResourceBundleReader.java
+src/com/ibm/icu/impl/JavaTimeZone.java
src/com/ibm/icu/impl/PatternTokenizer.java
src/com/ibm/icu/impl/Utility.java
src/com/ibm/icu/lang/UCharacter.java
diff --git a/src/com/ibm/icu/ICUConfig.properties b/src/com/ibm/icu/ICUConfig.properties
new file mode 100644
index 0000000..46667f9
--- /dev/null
+++ b/src/com/ibm/icu/ICUConfig.properties
@@ -0,0 +1,13 @@
+#*
+#*******************************************************************************
+#* Copyright (C) 2008-2012, International Business Machines Corporation and *
+#* others. All Rights Reserved. *
+#*******************************************************************************
+#* This is the properties contains ICU runtime configuration
+#*
+
+#
+# The default TimeZone implementation type used by the ICU TimeZone
+# factory method. [ ICU | JDK ]
+#
+com.ibm.icu.util.TimeZone.DefaultTimeZoneType = JDK
diff --git a/src/com/ibm/icu/dev/test/format/TimeZoneFormatTest.java b/src/com/ibm/icu/dev/test/format/TimeZoneFormatTest.java
index d4fc5c4..d906ae7 100644
--- a/src/com/ibm/icu/dev/test/format/TimeZoneFormatTest.java
+++ b/src/com/ibm/icu/dev/test/format/TimeZoneFormatTest.java
@@ -1,6 +1,6 @@
/*
*******************************************************************************
- * Copyright (C) 2007, Google, IBM and *
+ * Copyright (C) 2007-2012, Google, IBM and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@@ -11,6 +11,7 @@
import java.text.ParsePosition;
import java.util.Date;
+import com.ibm.icu.impl.ICUConfig;
import com.ibm.icu.impl.ZoneMeta;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.text.SimpleDateFormat;
@@ -23,6 +24,13 @@
public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
+ static final boolean isJDKTimeZone;
+
+ static {
+ String type = ICUConfig.get("com.ibm.icu.util.TimeZone.DefaultTimeZoneType", "ICU");
+ isJDKTimeZone = type.equalsIgnoreCase("JDK");
+ }
+
public static void main(String[] args) throws Exception {
new TimeZoneFormatTest().run(args);
}
@@ -121,30 +129,52 @@
int inOffset = inOffsets[0] + inOffsets[1];
int outOffset = outOffsets[0] + outOffsets[1];
if (inOffset != outOffset) {
- errln("Offset round trip failed; tz=" + tzids[tzidx]
- + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx]
- + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr
- + ", inOffset=" + inOffset + ", outOffset=" + outOffset);
+ if (isJDKTimeZone) {
+ logln("[JDKTZ] Offset round trip failed; tz=" + tzids[tzidx]
+ + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx]
+ + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr
+ + ", inOffset=" + inOffset + ", outOffset=" + outOffset);
+ } else {
+ errln("Offset round trip failed; tz=" + tzids[tzidx]
+ + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx]
+ + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr
+ + ", inOffset=" + inOffset + ", outOffset=" + outOffset);
+ }
}
} else if (PATTERNS[patidx].equals("z") || PATTERNS[patidx].equals("zzzz")
|| PATTERNS[patidx].equals("v") || PATTERNS[patidx].equals("vvvv")
|| PATTERNS[patidx].equals("V")) {
// Specific or generic: raw offset must be preserved.
if (inOffsets[0] != outOffsets[0]) {
- errln("Raw offset round trip failed; tz=" + tzids[tzidx]
- + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx]
- + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr
- + ", inRawOffset=" + inOffsets[0] + ", outRawOffset=" + outOffsets[0]);
+ if (isJDKTimeZone) {
+ logln("[JDKTZ] Raw offset round trip failed; tz=" + tzids[tzidx]
+ + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx]
+ + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr
+ + ", inRawOffset=" + inOffsets[0] + ", outRawOffset=" + outOffsets[0]);
+ } else {
+ errln("Raw offset round trip failed; tz=" + tzids[tzidx]
+ + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx]
+ + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr
+ + ", inRawOffset=" + inOffsets[0] + ", outRawOffset=" + outOffsets[0]);
+ }
}
} else { // "VVVV"
// Location: time zone rule must be preserved.
if (!outtz.getID().equals(ZoneMeta.getCanonicalID(tzids[tzidx]))) {
// Canonical ID did not match - check the rules
if (!((BasicTimeZone)outtz).hasEquivalentTransitions(tz, low, high)) {
- errln("Canonical round trip failed; tz=" + tzids[tzidx]
- + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx]
- + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr
- + ", outtz=" + outtz.getID());
+ if (isJDKTimeZone) {
+ logln("[JDKTZ] Canonical round trip failed; tz=" + tzids[tzidx]
+ + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx]
+ + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr
+ + ", outtz=" + outtz.getID());
+
+ } else {
+ errln("Canonical round trip failed; tz=" + tzids[tzidx]
+ + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx]
+ + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr
+ + ", outtz=" + outtz.getID());
+ }
}
}
}
@@ -225,7 +255,7 @@
// Skip aliases
continue;
}
- BasicTimeZone tz = (BasicTimeZone)TimeZone.getTimeZone(ids[zidx]);
+ BasicTimeZone tz = (BasicTimeZone)TimeZone.getTimeZone(ids[zidx], 0);
sdf.setTimeZone(tz);
long t = START_TIME;
@@ -279,7 +309,11 @@
.append(", restime=").append(restime)
.append(", diff=").append(restime - testTimes[testidx]);
if (expectedRoundTrip[testidx]) {
- errln("FAIL: " + msg.toString());
+ if (isJDKTimeZone) {
+ logln("[JDKTZ] " + msg.toString());
+ } else {
+ errln("FAIL: " + msg.toString());
+ }
} else if (REALLY_VERBOSE) {
logln(msg.toString());
}
diff --git a/src/com/ibm/icu/dev/test/serializable/SerializableTest.java b/src/com/ibm/icu/dev/test/serializable/SerializableTest.java
index 4e9b306..4841da5 100644
--- a/src/com/ibm/icu/dev/test/serializable/SerializableTest.java
+++ b/src/com/ibm/icu/dev/test/serializable/SerializableTest.java
@@ -1,7 +1,7 @@
//##header J2SE15
/*
*******************************************************************************
- * Copyright (C) 1996-2007, International Business Machines Corporation and *
+ * Copyright (C) 1996-2012, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@@ -14,6 +14,7 @@
import java.util.Locale;
import com.ibm.icu.dev.test.TestFmwk;
+import com.ibm.icu.impl.JavaTimeZone;
import com.ibm.icu.impl.OlsonTimeZone;
import com.ibm.icu.impl.TimeZoneAdapter;
import com.ibm.icu.math.BigDecimal;
@@ -579,6 +580,20 @@
}
}
+ private static class JavaTimeZoneHandler implements Handler {
+ public Object[] getTestObjects() {
+ JavaTimeZone data[] = new JavaTimeZone[1];
+ data[0] = new JavaTimeZone("America/New_York");
+ return data;
+ }
+ public boolean hasSameBehavior(Object a, Object b) {
+ JavaTimeZone jtza = (JavaTimeZone) a;
+ JavaTimeZone jtzb = (JavaTimeZone) b;
+
+ return jtza.equals(jtzb);
+ }
+ }
+
private static HashMap map = new HashMap();
static {
@@ -637,6 +652,8 @@
//#endif
map.put("com.ibm.icu.impl.duration.BasicDurationFormat", new FormatTests.BasicDurationFormatHandler());
map.put("com.ibm.icu.impl.RelativeDateFormat", new FormatTests.RelativeDateFormatHandler());
+
+ map.put("com.ibm.icu.impl.JavaTimeZone", new JavaTimeZoneHandler());
}
public SerializableTest()
diff --git a/src/com/ibm/icu/dev/test/timezone/TimeZoneOffsetLocalTest.java b/src/com/ibm/icu/dev/test/timezone/TimeZoneOffsetLocalTest.java
index 6841f20..abe0f92 100644
--- a/src/com/ibm/icu/dev/test/timezone/TimeZoneOffsetLocalTest.java
+++ b/src/com/ibm/icu/dev/test/timezone/TimeZoneOffsetLocalTest.java
@@ -1,6 +1,6 @@
/*
*******************************************************************************
- * Copyright (C) 2007, International Business Machines Corporation and *
+ * Copyright (C) 2007-2012, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@@ -113,7 +113,7 @@
// Set up TimeZone objects - OlsonTimeZone, SimpleTimeZone and RuleBasedTimeZone
BasicTimeZone[] TESTZONES = new BasicTimeZone[3];
- TESTZONES[0] = (BasicTimeZone)TimeZone.getTimeZone("America/Los_Angeles");
+ TESTZONES[0] = (BasicTimeZone)TimeZone.getTimeZone("America/Los_Angeles", 0);
TESTZONES[1] = new SimpleTimeZone(-8*HOUR, "Simple Pacific Time",
Calendar.APRIL, 1, Calendar.SUNDAY, 2*HOUR,
Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*HOUR);
diff --git a/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java b/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java
index dd0c49c..32999b1 100644
--- a/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java
+++ b/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java
@@ -1,6 +1,6 @@
/*
*******************************************************************************
- * Copyright (C) 2007, International Business Machines Corporation and *
+ * Copyright (C) 2007-2012, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@@ -208,7 +208,7 @@
*/
public void TestHistoricalRuleBasedTimeZone() {
// Compare to America/New_York with equivalent RBTZ
- TimeZone ny = TimeZone.getTimeZone("America/New_York");
+ TimeZone ny = TimeZone.getTimeZone("America/New_York", 0);
//RBTZ
InitialTimeZoneRule ir = new InitialTimeZoneRule("EST", -5*HOUR, 0);
@@ -321,7 +321,7 @@
public void TestOlsonTransition() {
String[] zids = getTestZIDs();
for (int i = 0; i < zids.length; i++) {
- TimeZone tz = TimeZone.getTimeZone(zids[i]);
+ TimeZone tz = TimeZone.getTimeZone(zids[i], 0);
if (tz == null) {
break;
}
@@ -350,7 +350,7 @@
String[] zids = getTestZIDs();
for (int i = 0; i < zids.length; i++) {
- TimeZone tz = TimeZone.getTimeZone(zids[i]);
+ TimeZone tz = TimeZone.getTimeZone(zids[i], 0);
if (tz == null) {
break;
}
@@ -385,9 +385,9 @@
public void TestHasEquivalentTransitions() {
// America/New_York and America/Indiana/Indianapolis are equivalent
// since 2006
- TimeZone newyork = TimeZone.getTimeZone("America/New_York");
- TimeZone indianapolis = TimeZone.getTimeZone("America/Indiana/Indianapolis");
- TimeZone gmt_5 = TimeZone.getTimeZone("Etc/GMT+5");
+ TimeZone newyork = TimeZone.getTimeZone("America/New_York", 0);
+ TimeZone indianapolis = TimeZone.getTimeZone("America/Indiana/Indianapolis", 0);
+ TimeZone gmt_5 = TimeZone.getTimeZone("Etc/GMT+5", 0);
long jan1_1971 = getUTCMillis(1971, Calendar.JANUARY, 1);
long jan1_2005 = getUTCMillis(2005, Calendar.JANUARY, 1);
@@ -436,7 +436,7 @@
String[] tzids = getTestZIDs();
for (int i = 0; i < tzids.length; i++) {
- BasicTimeZone olsontz = (BasicTimeZone)TimeZone.getTimeZone(tzids[i]);
+ BasicTimeZone olsontz = (BasicTimeZone)TimeZone.getTimeZone(tzids[i], 0);
VTimeZone vtz_org = VTimeZone.create(tzids[i]);
vtz_org.setTZURL("http://source.icu-project.org/timezone");
vtz_org.setLastModified(new Date());
@@ -510,7 +510,7 @@
for (int n = 0; n < startTimes.length; n++) {
long startTime = startTimes[n];
for (int i = 0; i < tzids.length; i++) {
- BasicTimeZone olsontz = (BasicTimeZone)TimeZone.getTimeZone(tzids[i]);
+ BasicTimeZone olsontz = (BasicTimeZone)TimeZone.getTimeZone(tzids[i], 0);
VTimeZone vtz_org = VTimeZone.create(tzids[i]);
VTimeZone vtz_new = null;
try {
@@ -690,7 +690,7 @@
for (int n = 0; n < testTimes.length; n++) {
long time = testTimes[n];
for (int i = 0; i < tzids.length; i++) {
- BasicTimeZone tz = (BasicTimeZone)TimeZone.getTimeZone(tzids[i]);
+ BasicTimeZone tz = (BasicTimeZone)TimeZone.getTimeZone(tzids[i], 0);
TimeZoneRule[] rules = tz.getSimpleTimeZoneRulesNear(time);
if (rules == null) {
errln("FAIL: Failed to extract simple rules for " + tzids[i] + " at " + time);
@@ -1107,7 +1107,7 @@
*/
public void TestVTimeZoneCoverage() {
final String TZID = "Europe/Moscow";
- BasicTimeZone otz = (BasicTimeZone)TimeZone.getTimeZone(TZID);
+ BasicTimeZone otz = (BasicTimeZone)TimeZone.getTimeZone(TZID, 0);
VTimeZone vtz = VTimeZone.create(TZID);
// getOffset(era, year, month, day, dayOfWeek, milliseconds)
diff --git a/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java b/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java
index 9710ca7..7078d37 100644
--- a/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java
+++ b/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java
@@ -1,6 +1,6 @@
/**
*******************************************************************************
- * Copyright (C) 2000-2010, International Business Machines Corporation and *
+ * Copyright (C) 2000-2012, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@@ -15,11 +15,11 @@
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Date;
-import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import com.ibm.icu.dev.test.TestFmwk;
+import com.ibm.icu.impl.ICUConfig;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.OlsonTimeZone;
import com.ibm.icu.text.SimpleDateFormat;
@@ -40,6 +40,21 @@
{
static final int millisPerHour = 3600000;
+ // TODO: We should probably read following data at runtime, so we can update
+ // the these values every release with necessary data changes.
+
+ // Some test case data is current date/tzdata version sensitive and producing errors
+ // when year/rule are changed.
+ static final int REFERENCE_YEAR = 2012;
+ static final String REFERENCE_DATA_VERSION = "2012c";
+
+ static final boolean isJDKTimeZone;
+
+ static {
+ String type = ICUConfig.get("com.ibm.icu.util.TimeZone.DefaultTimeZoneType", "ICU");
+ isJDKTimeZone = type.equalsIgnoreCase("JDK");
+ }
+
public static void main(String[] args) throws Exception {
new TimeZoneTest().run(args);
}
@@ -106,75 +121,100 @@
*/
public void TestShortZoneIDs() throws Exception {
- ZoneDescriptor[] JDK_116_REFERENCE_LIST = {
- new ZoneDescriptor("MIT", -660, true), // updated to false when merging 2010j
- new ZoneDescriptor("HST", -600, false),
- new ZoneDescriptor("AST", -540, true),
- new ZoneDescriptor("PST", -480, true),
- new ZoneDescriptor("PNT", -420, false),
- new ZoneDescriptor("MST", -420, false),// updated Aug 2003 aliu
- new ZoneDescriptor("CST", -360, true),
- new ZoneDescriptor("IET", -300, true), // updated Feb 2006 srl
- new ZoneDescriptor("EST", -300, false),// updated Aug 2003 aliu
- new ZoneDescriptor("PRT", -240, false),
- new ZoneDescriptor("CNT", -210, true),
- new ZoneDescriptor("AGT", -180, false), // updated Oct 2009 yoshito
- new ZoneDescriptor("BET", -180, true),
- // new ZoneDescriptor("CAT", -60, false), // Wrong:
- // As of bug 4130885, fix CAT (Central Africa)
- new ZoneDescriptor("CAT", 120, false), // Africa/Harare
- new ZoneDescriptor("GMT", 0, false),
- new ZoneDescriptor("UTC", 0, false),
- new ZoneDescriptor("ECT", 60, true),
- new ZoneDescriptor("ART", 120, true),
- new ZoneDescriptor("EET", 120, true),
- new ZoneDescriptor("EAT", 180, false),
- // new ZoneDescriptor("MET", 210, true),
- // This is a standard Unix zone, so don't remap it - Liu 3Jan01
- // new ZoneDescriptor("NET", 240, false);
- // As of bug 4191164, fix NET
- new ZoneDescriptor("NET", 240, true),
- // PLT behaves differently under different JDKs, so we don't check it
- // new ZoneDescriptor("PLT", 300, false), // updated Oct 2003 aliu
- new ZoneDescriptor("IST", 330, false),
- new ZoneDescriptor("BST", 360, false), // updated May 2010 - no DST in year 2010+
- new ZoneDescriptor("VST", 420, false),
- new ZoneDescriptor("CTT", 480, false), // updated Oct 2003 aliu
- new ZoneDescriptor("JST", 540, false),
- new ZoneDescriptor("ACT", 570, false), // updated Oct 2003 aliu
- new ZoneDescriptor("AET", 600, true),
- new ZoneDescriptor("SST", 660, false),
- // new ZoneDescriptor("NST", 720, false),
- // As of bug 4130885, fix NST (New Zealand)
- new ZoneDescriptor("NST", 720, true), // Pacific/Auckland
-
- // [3Jan01 Liu] Three of these zones have been updated.
- // The CTT and ACT zones just remap to Asia/Shanghai
- // and Australia/Darwin. Since those zones have changed,
- // I have updated the table. The MET zone used to be mapped
- // to Asia/Tehran but since MET is a standard Unix zone named
- // in the source data we no longer do this in icu or icu4j.
- };
-
- Hashtable hash = new Hashtable();
-
- String[] ids = TimeZone.getAvailableIDs();
- for (int i=0; i<ids.length; ++i) {
- String id = ids[i];
- if (id.length() == 3) {
- hash.put(id, new ZoneDescriptor(TimeZone.getTimeZone(id)));
- }
+ // This test case is tzdata version sensitive.
+ boolean isNonReferenceTzdataVersion = false;
+ String tzdataVer = TimeZone.getTZDataVersion();
+ if (!tzdataVer.equals(REFERENCE_DATA_VERSION)) {
+ // Note: We want to display a warning message here if
+ // REFERENCE_DATA_VERSION is out of date - so we
+ // do not forget to update the value before GA.
+ isNonReferenceTzdataVersion = true;
+ logln("Warning: Active tzdata version (" + tzdataVer +
+ ") does not match the reference tzdata version ("
+ + REFERENCE_DATA_VERSION + ") for this test case data.");
}
- for (int i=0; i<JDK_116_REFERENCE_LIST.length; ++i) {
- ZoneDescriptor referenceZone = JDK_116_REFERENCE_LIST[i];
- ZoneDescriptor currentZone = (ZoneDescriptor)hash.get(referenceZone.getID());
+ if (isJDKTimeZone) {
+ logln("Warning: Using JDK TimeZone. Some test cases may not return expected results.");
+ }
+
+ // Note: useDaylightTime returns true if DST is observed
+ // in the time zone in the current calendar year. The test
+ // data is valid for the date after the reference year below.
+ // If system clock is before the year, some test cases may
+ // fail.
+ GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("Etc/GMT"));
+ cal.set(REFERENCE_YEAR, Calendar.JANUARY, 2); // day 2 in GMT
+
+ boolean isDateBeforeReferenceYear = System.currentTimeMillis() < cal.getTimeInMillis();
+ if (isDateBeforeReferenceYear) {
+ logln("Warning: Past time is set to the system clock. Some test cases may not return expected results.");
+ }
+
+ ZoneDescriptor[] REFERENCE_LIST = {
+ new ZoneDescriptor("HST", -600, false), // Olson northamerica -10:00
+ new ZoneDescriptor("AST", -540, true), // ICU Link - America/Anchorage
+ new ZoneDescriptor("PST", -480, true), // ICU Link - America/Los_Angeles
+ new ZoneDescriptor("PNT", -420, false), // ICU Link - America/Phoenix
+ new ZoneDescriptor("MST", -420, false), // updated Aug 2003 aliu
+ new ZoneDescriptor("CST", -360, true), // Olson northamerica -7:00
+ new ZoneDescriptor("IET", -300, true), // ICU Link - America/Indiana/Indianapolis
+ new ZoneDescriptor("EST", -300, false), // Olson northamerica -5:00
+ new ZoneDescriptor("PRT", -240, false), // ICU Link - America/Puerto_Rico
+ new ZoneDescriptor("CNT", -210, true), // ICU Link - America/St_Johns
+ new ZoneDescriptor("AGT", -180, false), // ICU Link - America/Argentina/Buenos_Aires
+ new ZoneDescriptor("BET", -180, true), // ICU Link - America/Sao_Paulo
+ new ZoneDescriptor("GMT", 0, false), // Olson etcetera Link - Etc/GMT
+ new ZoneDescriptor("UTC", 0, false), // Olson etcetera 0
+ new ZoneDescriptor("ECT", 60, true), // ICU Link - Europe/Paris
+ new ZoneDescriptor("MET", 60, true), // Olson europe 1:00 C-Eur
+ new ZoneDescriptor("CAT", 120, false), // ICU Link - Africa/Harare
+ new ZoneDescriptor("ART", 120, false), // ICU Link - Africa/Cairo
+ new ZoneDescriptor("EET", 120, true), // Olson europe 2:00 EU
+ new ZoneDescriptor("EAT", 180, false), // ICU Link - Africa/Addis_Ababa
+ new ZoneDescriptor("NET", 240, false), // ICU Link - Asia/Yerevan
+ new ZoneDescriptor("PLT", 300, false), // ICU Link - Asia/Karachi
+ new ZoneDescriptor("IST", 330, false), // ICU Link - Asia/Kolkata
+ new ZoneDescriptor("BST", 360, false), // ICU Link - Asia/Dhaka
+ new ZoneDescriptor("VST", 420, false), // ICU Link - Asia/Ho_Chi_Minh
+ new ZoneDescriptor("CTT", 480, false), // ICU Link - Asia/Shanghai
+ new ZoneDescriptor("JST", 540, false), // ICU Link - Asia/Tokyo
+ new ZoneDescriptor("ACT", 570, false), // ICU Link - Australia/Darwin
+ new ZoneDescriptor("AET", 600, true), // ICU Link - Australia/Sydney
+ new ZoneDescriptor("SST", 660, false), // ICU Link - Pacific/Guadalcanal
+ new ZoneDescriptor("NST", 720, true), // ICU Link - Pacific/Auckland
+ new ZoneDescriptor("MIT", 780, true), // ICU Link - Pacific/Apia
+
+ new ZoneDescriptor("Etc/Unknown", 0, false), // CLDR
+
+ new ZoneDescriptor("SystemV/AST4ADT", -240, true),
+ new ZoneDescriptor("SystemV/EST5EDT", -300, true),
+ new ZoneDescriptor("SystemV/CST6CDT", -360, true),
+ new ZoneDescriptor("SystemV/MST7MDT", -420, true),
+ new ZoneDescriptor("SystemV/PST8PDT", -480, true),
+ new ZoneDescriptor("SystemV/YST9YDT", -540, true),
+ new ZoneDescriptor("SystemV/AST4", -240, false),
+ new ZoneDescriptor("SystemV/EST5", -300, false),
+ new ZoneDescriptor("SystemV/CST6", -360, false),
+ new ZoneDescriptor("SystemV/MST7", -420, false),
+ new ZoneDescriptor("SystemV/PST8", -480, false),
+ new ZoneDescriptor("SystemV/YST9", -540, false),
+ new ZoneDescriptor("SystemV/HST10", -600, false),
+ };
+
+ for (int i=0; i<REFERENCE_LIST.length; ++i) {
+ ZoneDescriptor referenceZone = REFERENCE_LIST[i];
+ ZoneDescriptor currentZone = new ZoneDescriptor(TimeZone.getTimeZone(referenceZone.getID()));
if (referenceZone.equals(currentZone)) {
logln("ok " + referenceZone);
- }
- else {
- warnln("Fail: Expected " + referenceZone +
- "; got " + currentZone);
+ } else {
+ if (isNonReferenceTzdataVersion || isJDKTimeZone || isDateBeforeReferenceYear) {
+ logln("Warning: Expected " + referenceZone +
+ "; got " + currentZone);
+ } else {
+ errln("Fail: Expected " + referenceZone +
+ "; got " + currentZone);
+ }
}
}
}
@@ -341,19 +381,33 @@
logln(id + " -> " + zone.getID() + " " + offset);
String gotID = zone.getID();
if (exp == null && !gotID.equals("GMT")) {
- errln("Expected parse failure for " + id +
- ", got offset of " + offset +
- ", id " + zone.getID());
+ if (isJDKTimeZone) {
+ logln("[JDK time zone mode] Expected parse failure with ICU for " + id +
+ ", got offset of " + offset +
+ ", id " + zone.getID());
+ } else {
+ errln("Expected parse failure for " + id +
+ ", got offset of " + offset +
+ ", id " + zone.getID());
+ }
}
// JDK 1.3 creates custom zones with the ID "Custom"
// JDK 1.4 creates custom zones with IDs of the form "GMT+02:00"
// ICU creates custom zones with IDs of the form "GMT+0200"
else if (exp != null && (ioffset != exp.intValue() || !(gotID.equals(expectedID)))) {
- errln("Expected offset of " + formatOffset(exp.intValue()) +
- ", id " + expectedID +
- ", for " + id +
- ", got offset of " + offset +
- ", id " + zone.getID());
+ if (isJDKTimeZone) {
+ logln("[JDK time zone mode] Expected offset of " + formatOffset(exp.intValue()) +
+ "with ICU, id " + expectedID +
+ ", for " + id +
+ ", got offset of " + offset +
+ ", id " + zone.getID());
+ } else {
+ errln("Expected offset of " + formatOffset(exp.intValue()) +
+ ", id " + expectedID +
+ ", for " + id +
+ ", got offset of " + offset +
+ ", id " + zone.getID());
+ }
}
}
}
diff --git a/src/com/ibm/icu/impl/ICUConfig.java b/src/com/ibm/icu/impl/ICUConfig.java
new file mode 100644
index 0000000..decbc71
--- /dev/null
+++ b/src/com/ibm/icu/impl/ICUConfig.java
@@ -0,0 +1,65 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 2008-2012, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.MissingResourceException;
+import java.util.Properties;
+
+/**
+ * ICUConfig is a class used for accessing ICU4J runtime configuration.
+ */
+public class ICUConfig {
+ public static final String CONFIG_PROPS_FILE = "/com/ibm/icu/ICUConfig.properties";
+ private static final Properties CONFIG_PROPS;
+
+ static {
+ CONFIG_PROPS = new Properties();
+ try {
+ InputStream is = ICUData.getStream(CONFIG_PROPS_FILE);
+ if (is != null) {
+ CONFIG_PROPS.load(is);
+ }
+ } catch (MissingResourceException mre) {
+ // If it does not exist, ignore.
+ } catch (IOException ioe) {
+ // Any IO errors, ignore
+ }
+ }
+
+ /**
+ * Get ICU configuration property value for the given name.
+ * @param name The configuration property name
+ * @return The configuration property value, or null if it does not exist.
+ */
+ public static String get(String name) {
+ return get(name, null);
+ }
+
+ /**
+ * Get ICU configuration property value for the given name.
+ * @param name The configuration property name
+ * @param def The default value
+ * @return The configuration property value. If the property does not
+ * exist, <code>def</code> is returned.
+ */
+ public static String get(String name, String def) {
+ String val = null;
+ // Try the system property first
+ try {
+ val = System.getProperty(name);
+ } catch (SecurityException e) {
+ // Ignore and fall through
+ }
+
+ if (val == null) {
+ val = CONFIG_PROPS.getProperty(name, def);
+ }
+ return val;
+ }
+}
diff --git a/src/com/ibm/icu/impl/JavaTimeZone.java b/src/com/ibm/icu/impl/JavaTimeZone.java
new file mode 100644
index 0000000..d9ceb77
--- /dev/null
+++ b/src/com/ibm/icu/impl/JavaTimeZone.java
@@ -0,0 +1,394 @@
+//##header J2SE15
+/*
+ *******************************************************************************
+ * Copyright (C) 2008-2012, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.impl;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.text.ParsePosition;
+import java.util.Date;
+import java.util.TreeSet;
+
+import com.ibm.icu.text.NumberFormat;
+import com.ibm.icu.util.TimeZone;
+
+/**
+ * JavaTimeZone inherits com.ibm.icu.util.TimeZone and wraps java.util.TimeZone.
+ * We used to have JDKTimeZone which wrapped Java TimeZone and used it as primary
+ * TimeZone implementation until ICU4J 3.4.1. This class works exactly like
+ * JDKTimeZone and allows ICU users who use ICU4J and JDK date/time/calendar
+ * services in mix to maintain only JDK timezone rules.
+ *
+ * This TimeZone subclass is returned by the TimeZone factory method getTimeZone(String)
+ * when the default timezone type in TimeZone class is TimeZone.TIMEZONE_JDK.
+ */
+public class JavaTimeZone extends TimeZone {
+
+ private static final long serialVersionUID = 6977448185543929364L;
+
+ private static final TreeSet AVAILABLESET;
+
+ private java.util.TimeZone javatz;
+ private transient java.util.Calendar javacal;
+
+ static {
+ AVAILABLESET = new TreeSet();
+ String[] availableIds = java.util.TimeZone.getAvailableIDs();
+ for (int i = 0; i < availableIds.length; i++) {
+ AVAILABLESET.add(availableIds[i]);
+ }
+ }
+
+ /**
+ * Constructs a JavaTimeZone with the default Java TimeZone
+ */
+ public JavaTimeZone() {
+ javatz = java.util.TimeZone.getDefault();
+ setID(javatz.getID());
+ javacal = new java.util.GregorianCalendar(javatz);
+ }
+
+ /**
+ * Constructs a JavaTimeZone with the given timezone ID.
+ * @param id A timezone ID, either a system ID or a custom ID.
+ */
+ public JavaTimeZone(String id) {
+ if (AVAILABLESET.contains(id)) {
+ javatz = java.util.TimeZone.getTimeZone(id);
+ }
+
+ if (javatz == null) {
+ // Use ICU's canonical ID mapping
+ if (id.equals("Etc/Unknown")) {
+ // Special CLDR ID
+ javatz = java.util.TimeZone.getTimeZone("GMT");
+ javatz.setID("Etc/Unknown");
+
+ } else {
+ String canonicalID = ZoneMeta.getOlsonCanonicalID(id);
+ if (canonicalID != null && AVAILABLESET.contains(canonicalID)) {
+ javatz = java.util.TimeZone.getTimeZone(canonicalID);
+ }
+ }
+ }
+
+ if (javatz == null){
+ int[] fields = new int[4];
+ if (parseCustomID(id, fields)) {
+ // JDK does not support offset seconds.
+ // If custom ID, we create java.util.SimpleTimeZone here.
+ id = formatCustomID(fields[1], fields[2], fields[3], fields[0] < 0);
+ int offset = fields[0] * ((fields[1] * 60 + fields[2]) * 60 + fields[3]) * 1000;
+ javatz = new java.util.SimpleTimeZone(offset, id);
+ }
+ }
+
+ if (javatz == null) {
+ // Final fallback
+ id = "GMT";
+ javatz = java.util.TimeZone.getTimeZone(id);
+ }
+ setID(id);
+ javacal = new java.util.GregorianCalendar(javatz);
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.util.TimeZone#getOffset(int, int, int, int, int, int)
+ */
+ public int getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds) {
+ return javatz.getOffset(era, year, month, day, dayOfWeek, milliseconds);
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.util.TimeZone#getOffset(long, boolean, int[])
+ */
+ public void getOffset(long date, boolean local, int[] offsets) {
+ synchronized (javacal) {
+ if (local) {
+ int fields[] = new int[6];
+ Grego.timeToFields(date, fields);
+ int hour, min, sec, mil;
+ int tmp = fields[5];
+ mil = tmp % 1000;
+ tmp /= 1000;
+ sec = tmp % 60;
+ tmp /= 60;
+ min = tmp % 60;
+ hour = tmp / 60;
+ javacal.clear();
+ javacal.set(fields[0], fields[1], fields[2], hour, min, sec);
+ javacal.set(java.util.Calendar.MILLISECOND, mil);
+
+ int doy1, hour1, min1, sec1, mil1;
+ doy1 = javacal.get(java.util.Calendar.DAY_OF_YEAR);
+ hour1 = javacal.get(java.util.Calendar.HOUR_OF_DAY);
+ min1 = javacal.get(java.util.Calendar.MINUTE);
+ sec1 = javacal.get(java.util.Calendar.SECOND);
+ mil1 = javacal.get(java.util.Calendar.MILLISECOND);
+
+ if (fields[4] != doy1 || hour != hour1 || min != min1 || sec != sec1 || mil != mil1) {
+ // Calendar field(s) were changed due to the adjustment for non-existing time
+ // Note: This code does not support non-existing local time at year boundary properly.
+ // But, it should work fine for real timezones.
+ int dayDelta = Math.abs(doy1 - fields[4]) > 1 ? 1 : doy1 - fields[4];
+ int delta = ((((dayDelta * 24) + hour1 - hour) * 60 + min1 - min) * 60 + sec1 - sec) * 1000 + mil1 - mil;
+
+ // In this case, we use the offsets before the transition
+//#if defined(FOUNDATION10) || defined(J2SE13)
+//## javacal.setTime(new Date(javacal.getTime().getTime() - delta - 1));
+//#else
+ javacal.setTimeInMillis(javacal.getTimeInMillis() - delta - 1);
+//#endif
+ }
+ } else {
+//#if defined(FOUNDATION10) || defined(J2SE13)
+//## javacal.setTime(new Date(date));
+//#else
+ javacal.setTimeInMillis(date);
+//#endif
+ }
+ offsets[0] = javacal.get(java.util.Calendar.ZONE_OFFSET);
+ offsets[1] = javacal.get(java.util.Calendar.DST_OFFSET);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.util.TimeZone#getRawOffset()
+ */
+ public int getRawOffset() {
+ return javatz.getRawOffset();
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.util.TimeZone#inDaylightTime(java.util.Date)
+ */
+ public boolean inDaylightTime(Date date) {
+ return javatz.inDaylightTime(date);
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.util.TimeZone#setRawOffset(int)
+ */
+ public void setRawOffset(int offsetMillis) {
+ javatz.setRawOffset(offsetMillis);
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.util.TimeZone#useDaylightTime()
+ */
+ public boolean useDaylightTime() {
+ return javatz.useDaylightTime();
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.util.TimeZone#getDSTSavings()
+ */
+ public int getDSTSavings() {
+ int dstSavings = super.getDSTSavings();
+ try {
+ // hack so test compiles and runs in both JDK 1.3 and JDK 1.4+
+ final Object[] args = new Object[0];
+ final Class[] argtypes = new Class[0];
+ java.lang.reflect.Method m = javatz.getClass().getMethod("getDSTSavings", argtypes);
+ dstSavings = ((Integer) m.invoke(javatz, args)).intValue();
+ } catch (Exception e) {
+ // just use the result returned by super.getDSTSavings()
+ }
+ return dstSavings;
+ }
+
+ public java.util.TimeZone unwrap() {
+ return javatz;
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.util.TimeZone#clone()
+ */
+ public Object clone() {
+ JavaTimeZone other = (JavaTimeZone)super.clone();
+ other.javatz = (java.util.TimeZone)javatz.clone();
+ return other;
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.util.TimeZone#hashCode()
+ */
+ public int hashCode() {
+ return super.hashCode() + javatz.hashCode();
+ }
+
+ private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
+ s.defaultReadObject();
+ javacal = new java.util.GregorianCalendar(javatz);
+ }
+
+
+ private static final String kGMT_ID = "GMT";
+ private static final String kCUSTOM_TZ_PREFIX = "GMT";
+
+ // Maximum value of valid custom time zone hour/min
+ private static final int kMAX_CUSTOM_HOUR = 23;
+ private static final int kMAX_CUSTOM_MIN = 59;
+ private static final int kMAX_CUSTOM_SEC = 59;
+
+ /*
+ * Parses the given custom time zone identifier
+ * @param id id A string of the form GMT[+-]hh:mm, GMT[+-]hhmm, or
+ * GMT[+-]hh.
+ * @param fields An array of int (length = 4) to receive the parsed
+ * offset time fields. The sign is set to fields[0] (-1 or 1),
+ * hour is set to fields[1], minute is set to fields[2] and second is
+ * set to fields[3].
+ * @return Returns true when the given custom id is valid.
+ */
+ static boolean parseCustomID(String id, int[] fields) {
+ NumberFormat numberFormat = null;
+ String idUppercase = id.toUpperCase();
+
+ if (id != null && id.length() > kGMT_ID.length() &&
+ idUppercase.startsWith(kGMT_ID)) {
+ ParsePosition pos = new ParsePosition(kGMT_ID.length());
+ int sign = 1;
+ int hour = 0;
+ int min = 0;
+ int sec = 0;
+
+ if (id.charAt(pos.getIndex()) == 0x002D /*'-'*/) {
+ sign = -1;
+ } else if (id.charAt(pos.getIndex()) != 0x002B /*'+'*/) {
+ return false;
+ }
+ pos.setIndex(pos.getIndex() + 1);
+
+ numberFormat = NumberFormat.getInstance();
+ numberFormat.setParseIntegerOnly(true);
+
+ // Look for either hh:mm, hhmm, or hh
+ int start = pos.getIndex();
+
+ Number n = numberFormat.parse(id, pos);
+ if (pos.getIndex() == start) {
+ return false;
+ }
+ hour = n.intValue();
+
+ if (pos.getIndex() < id.length()){
+ if (pos.getIndex() - start > 2
+ || id.charAt(pos.getIndex()) != 0x003A /*':'*/) {
+ return false;
+ }
+ // hh:mm
+ pos.setIndex(pos.getIndex() + 1);
+ int oldPos = pos.getIndex();
+ n = numberFormat.parse(id, pos);
+ if ((pos.getIndex() - oldPos) != 2) {
+ // must be 2 digits
+ return false;
+ }
+ min = n.intValue();
+ if (pos.getIndex() < id.length()) {
+ if (id.charAt(pos.getIndex()) != 0x003A /*':'*/) {
+ return false;
+ }
+ // [:ss]
+ pos.setIndex(pos.getIndex() + 1);
+ oldPos = pos.getIndex();
+ n = numberFormat.parse(id, pos);
+ if (pos.getIndex() != id.length()
+ || (pos.getIndex() - oldPos) != 2) {
+ return false;
+ }
+ sec = n.intValue();
+ }
+ } else {
+ // Supported formats are below -
+ //
+ // HHmmss
+ // Hmmss
+ // HHmm
+ // Hmm
+ // HH
+ // H
+
+ int length = pos.getIndex() - start;
+ if (length <= 0 || 6 < length) {
+ // invalid length
+ return false;
+ }
+ switch (length) {
+ case 1:
+ case 2:
+ // already set to hour
+ break;
+ case 3:
+ case 4:
+ min = hour % 100;
+ hour /= 100;
+ break;
+ case 5:
+ case 6:
+ sec = hour % 100;
+ min = (hour/100) % 100;
+ hour /= 10000;
+ break;
+ }
+ }
+
+ if (hour <= kMAX_CUSTOM_HOUR && min <= kMAX_CUSTOM_MIN && sec <= kMAX_CUSTOM_SEC) {
+ if (fields != null) {
+ if (fields.length >= 1) {
+ fields[0] = sign;
+ }
+ if (fields.length >= 2) {
+ fields[1] = hour;
+ }
+ if (fields.length >= 3) {
+ fields[2] = min;
+ }
+ if (fields.length >= 4) {
+ fields[3] = sec;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /*
+ * Returns the normalized custom TimeZone ID
+ */
+ static String formatCustomID(int hour, int min, int sec, boolean negative) {
+ // Create normalized time zone ID - GMT[+|-]hhmm[ss]
+ StringBuffer zid = new StringBuffer(kCUSTOM_TZ_PREFIX);
+ if (hour != 0 || min != 0) {
+ if(negative) {
+ zid.append('-');
+ } else {
+ zid.append('+');
+ }
+ // Always use US-ASCII digits
+ if (hour < 10) {
+ zid.append('0');
+ }
+ zid.append(hour);
+ if (min < 10) {
+ zid.append('0');
+ }
+ zid.append(min);
+
+ if (sec != 0) {
+ // Optional second field
+ if (sec < 10) {
+ zid.append('0');
+ }
+ zid.append(sec);
+ }
+ }
+ return zid.toString();
+ }
+}
diff --git a/src/com/ibm/icu/impl/data/icudata.jar b/src/com/ibm/icu/impl/data/icudata.jar
index cdce91e..86d8c57 100755
--- a/src/com/ibm/icu/impl/data/icudata.jar
+++ b/src/com/ibm/icu/impl/data/icudata.jar
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:fc44b1203dde80ce45566deee764eb77bc69f8dc2f87e72a07f36798846862fa
-size 5450591
+oid sha256:d580ce04b0d0fceafce80c6cd40e6f2d8ece3f1e0570b6c218f74b234f91d3a0
+size 5456288
diff --git a/src/com/ibm/icu/util/TimeZone.java b/src/com/ibm/icu/util/TimeZone.java
index 87e8abe..de8fea7 100644
--- a/src/com/ibm/icu/util/TimeZone.java
+++ b/src/com/ibm/icu/util/TimeZone.java
@@ -1,7 +1,7 @@
/*
* @(#)TimeZone.java 1.51 00/01/19
*
- * Copyright (C) 1996-2007, International Business Machines
+ * Copyright (C) 1996-2012, International Business Machines
* Corporation and others. All Rights Reserved.
*/
@@ -14,6 +14,8 @@
import java.util.Locale;
import com.ibm.icu.impl.Grego;
+import com.ibm.icu.impl.ICUConfig;
+import com.ibm.icu.impl.JavaTimeZone;
import com.ibm.icu.impl.TimeZoneAdapter;
import com.ibm.icu.impl.ZoneMeta;
import com.ibm.icu.text.SimpleDateFormat;
@@ -83,6 +85,19 @@
}
/**
+ * A time zone implementation type indicating ICU's own TimeZone used by
+ * <code>getTimeZone</code>, <code>setDefaultTimeZoneType</code>
+ * and <code>getDefaultTimeZoneType</code>.
+ */
+ private static final int TIMEZONE_ICU = 0;
+ /**
+ * A time zone implementation type indicating JDK TimeZone used by
+ * <code>getTimeZone</code>, <code>setDefaultTimeZoneType</code>
+ * and <code>getDefaultTimeZoneType</code>.
+ */
+ private static final int TIMEZONE_JDK = 1;
+
+ /**
* A style specifier for <code>getDisplayName()</code> indicating
* a short name, such as "PST."
* @see #LONG
@@ -576,24 +591,45 @@
* @stable ICU 2.0
*/
public static synchronized TimeZone getTimeZone(String ID) {
- /* We first try to lookup the zone ID in our system list. If this
- * fails, we try to parse it as a custom string GMT[+-]hh:mm. If
- * all else fails, we return GMT, which is probably not what the
- * user wants, but at least is a functioning TimeZone object.
- *
- * We cannot return NULL, because that would break compatibility
- * with the JDK.
- */
- if(ID==null){
- throw new NullPointerException();
- }
- TimeZone result = ZoneMeta.getSystemTimeZone(ID);
-
- if (result == null) {
- result = ZoneMeta.getCustomTimeZone(ID);
- }
- if (result == null) {
- result = ZoneMeta.getGMT();
+ return getTimeZone(ID, TZ_IMPL);
+ }
+
+ /**
+ * Gets the <code>TimeZone</code> for the given ID and the timezone type.
+ * @param ID the ID for a <code>TimeZone</code>, either an abbreviation
+ * such as "PST", a full name such as "America/Los_Angeles", or a custom
+ * ID such as "GMT-8:00". Note that the support of abbreviations is
+ * for JDK 1.1.x compatibility only and full names should be used.
+ * @param type Timezone type, either <code>TIMEZONE_ICU</code> or <code>TIMEZONE_JDK</code>.
+ * @return the specified <code>TimeZone</code>, or the GMT zone if the given ID
+ * cannot be understood.
+ * @internal
+ * @deprecated This API is ICU internal only.
+ */
+ public static synchronized TimeZone getTimeZone(String ID, int type) {
+ TimeZone result;
+ if (type == TIMEZONE_JDK) {
+ result = new JavaTimeZone(ID);
+ } else {
+ /* We first try to lookup the zone ID in our system list. If this
+ * fails, we try to parse it as a custom string GMT[+-]hh:mm. If
+ * all else fails, we return GMT, which is probably not what the
+ * user wants, but at least is a functioning TimeZone object.
+ *
+ * We cannot return NULL, because that would break compatibility
+ * with the JDK.
+ */
+ if(ID==null){
+ throw new NullPointerException();
+ }
+ result = ZoneMeta.getSystemTimeZone(ID);
+
+ if (result == null) {
+ result = ZoneMeta.getCustomTimeZone(ID);
+ }
+ if (result == null) {
+ result = ZoneMeta.getGMT();
+ }
}
return result;
}
@@ -691,8 +727,12 @@
*/
public static synchronized TimeZone getDefault() {
if (defaultZone == null) {
- java.util.TimeZone temp=java.util.TimeZone.getDefault();
- defaultZone = getTimeZone(temp.getID());
+ if (TZ_IMPL == TIMEZONE_JDK) {
+ defaultZone = new JavaTimeZone();
+ } else {
+ java.util.TimeZone temp = java.util.TimeZone.getDefault();
+ defaultZone = getTimeZone(temp.getID());
+ }
}
return (TimeZone) defaultZone.clone();
}
@@ -706,14 +746,36 @@
* @stable ICU 2.0
*/
public static synchronized void setDefault(TimeZone tz) {
-
defaultZone = tz;
+ java.util.TimeZone jdkZone = null;
+ if (defaultZone instanceof JavaTimeZone) {
+ jdkZone = ((JavaTimeZone)defaultZone).unwrap();
+ } else {
// Keep java.util.TimeZone default in sync so java.util.Date
// can interoperate with com.ibm.icu.util classes.
- java.util.TimeZone jdkZone = null;
+
if (tz != null) {
+ if (tz instanceof com.ibm.icu.impl.OlsonTimeZone) {
+ // Because of the lack of APIs supporting historic
+ // zone offset/dst saving in JDK TimeZone,
+ // wrapping ICU TimeZone with JDK TimeZone will
+ // cause historic offset calculation in Calendar/Date.
+ // JDK calendar implementation calls getRawOffset() and
+ // getDSTSavings() when the instance of JDK TimeZone
+ // is not an instance of JDK internal TimeZone subclass
+ // (sun.util.calendar.ZoneInfo). Ticket#6459
+ String icuID = tz.getID();
+ jdkZone = java.util.TimeZone.getTimeZone(icuID);
+ if (!icuID.equals(jdkZone.getID())) {
+ // JDK does not know the ID..
+ jdkZone = null;
+ }
+ }
+ if (jdkZone == null) {
jdkZone = TimeZoneAdapter.wrap(tz);
}
+ }
+ }
java.util.TimeZone.setDefault(jdkZone);
}
@@ -808,6 +870,24 @@
*/
private static String TZDATA_VERSION = null;
+ /**
+ * TimeZone implementation type
+ */
+ private static int TZ_IMPL = TIMEZONE_ICU;
+
+ /**
+ * TimeZone implementation type initialization
+ */
+ private static final String TZIMPL_CONFIG_KEY = "com.ibm.icu.util.TimeZone.DefaultTimeZoneType";
+ private static final String TZIMPL_CONFIG_ICU = "ICU";
+ private static final String TZIMPL_CONFIG_JDK = "JDK";
+
+ static {
+ String type = ICUConfig.get(TZIMPL_CONFIG_KEY, TZIMPL_CONFIG_ICU);
+ if (type.equalsIgnoreCase(TZIMPL_CONFIG_JDK)) {
+ TZ_IMPL = TIMEZONE_JDK;
+ }
+ }
}
//eof
diff --git a/src/com/ibm/icu/util/VTimeZone.java b/src/com/ibm/icu/util/VTimeZone.java
index 03bd04e..0bd393e 100644
--- a/src/com/ibm/icu/util/VTimeZone.java
+++ b/src/com/ibm/icu/util/VTimeZone.java
@@ -1,6 +1,6 @@
/*
*******************************************************************************
- * Copyright (C) 2007, International Business Machines Corporation and *
+ * Copyright (C) 2007-2012, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@@ -49,7 +49,7 @@
*/
public static VTimeZone create(String tzid) {
VTimeZone vtz = new VTimeZone();
- vtz.tz = (BasicTimeZone)TimeZone.getTimeZone(tzid);
+ vtz.tz = (BasicTimeZone)TimeZone.getTimeZone(tzid, 0);
vtz.olsonzid = vtz.tz.getID();
vtz.setID(tzid);