ICU-5990 metazoneInfo.res support. Fixed a bug for detecting daylight saving time amount. Updated icudata.jar to include metazoneInfo.res.
X-SVN-Rev: 22968
diff --git a/icu4j/src/com/ibm/icu/dev/test/format/TimeZoneFormatTest.java b/icu4j/src/com/ibm/icu/dev/test/format/TimeZoneFormatTest.java
index b7920d3..d4fc5c4 100644
--- a/icu4j/src/com/ibm/icu/dev/test/format/TimeZoneFormatTest.java
+++ b/icu4j/src/com/ibm/icu/dev/test/format/TimeZoneFormatTest.java
@@ -208,6 +208,7 @@
};
}
+ long testCounts = 0;
long[] testTimes = new long[4];
boolean[] expectedRoundTrip = new boolean[4];
int testLen = 0;
@@ -219,7 +220,6 @@
SimpleDateFormat sdf = new SimpleDateFormat(pattern, LOCALES[locidx]);
String[] ids = TimeZone.getAvailableIDs();
- timer = System.currentTimeMillis();
for (int zidx = 0; zidx < ids.length; zidx++) {
if(!ids[zidx].equals(ZoneMeta.getCanonicalID(ids[zidx]))) {
// Skip aliases
@@ -262,6 +262,8 @@
}
}
for (int testidx = 0; testidx < testLen; testidx++) {
+ testCounts++;
+ timer = System.currentTimeMillis();
String text = sdf.format(new Date(testTimes[testidx]));
try {
Date parsedDate = sdf.parse(text);
@@ -285,6 +287,7 @@
} catch (ParseException pe) {
errln("FAIL: " + pe.getMessage());
}
+ times[patidx] += System.currentTimeMillis() - timer;
}
tzt = tz.getNextTransition(t, false);
if (tzt == null) {
@@ -300,7 +303,6 @@
}
}
}
- times[patidx] += System.currentTimeMillis() - timer;
}
}
@@ -311,5 +313,6 @@
total += times[i];
}
logln("Total: " + total + "ms");
+ logln("Iteration: " + testCounts);
}
}
\ No newline at end of file
diff --git a/icu4j/src/com/ibm/icu/impl/ZoneMeta.java b/icu4j/src/com/ibm/icu/impl/ZoneMeta.java
index aaa855f..80850d3 100644
--- a/icu4j/src/com/ibm/icu/impl/ZoneMeta.java
+++ b/icu4j/src/com/ibm/icu/impl/ZoneMeta.java
@@ -747,66 +747,20 @@
}
static Map getOlsonToMetaMap() {
- HashMap olsonToMeta = null;
+ Map olsonToMeta = null;
synchronized(ZoneMeta.class) {
if (OLSON_TO_META_REF != null) {
olsonToMeta = (HashMap)OLSON_TO_META_REF.get();
}
if (olsonToMeta == null) {
- // Create olson id to metazone mapping table
- olsonToMeta = new HashMap();
- UResourceBundle zoneStringsBundle = null;
- try {
- UResourceBundle bundle = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "root");
- zoneStringsBundle = bundle.get("zoneStrings");
- } catch (MissingResourceException mre) {
- // do nothing
+ olsonToMeta = createOlsonToMetaMap();
+ if (olsonToMeta == null) {
+ // We may not need this code for ICU4J...
+ olsonToMeta = createOlsonToMetaMapOld();
}
- if (zoneStringsBundle != null) {
- // DateFormat to be used for parsing metazone mapping range
- SimpleDateFormat mzdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
- mzdf.setTimeZone(TimeZone.getTimeZone("UTC"));
-
- String[] tzids = getAvailableIDs();
- for (int i = 0; i < tzids.length; i++) {
- // Skip aliases
- if (!tzids[i].equals(getCanonicalID(tzids[i]))) {
- continue;
- }
- String tzkey = tzids[i].replace('/', ':');
- try {
- UResourceBundle zoneBundle = zoneStringsBundle.get(tzkey);
- UResourceBundle useMZ = zoneBundle.get("um");
- LinkedList mzMappings = new LinkedList();
- for (int idx = 0; ; idx++) {
- try {
- UResourceBundle mz = useMZ.get("mz" + idx);
- String[] mzstr = mz.getStringArray();
- if (mzstr == null || mzstr.length != 3) {
- continue;
- }
- OlsonToMetaMappingEntry mzmap = new OlsonToMetaMappingEntry();
- mzmap.mzid = mzstr[0].intern();
- mzmap.from = mzdf.parse(mzstr[1]).getTime();
- mzmap.to = mzdf.parse(mzstr[2]).getTime();
-
- // Add this mapping to the list
- mzMappings.add(mzmap);
- } catch (MissingResourceException nomz) {
- // we're done
- break;
- } catch (ParseException baddate) {
- // skip this
- }
- }
- if (mzMappings.size() != 0) {
- // Add to the olson-to-meta map
- olsonToMeta.put(tzids[i], mzMappings);
- }
- } catch (MissingResourceException noum) {
- // Does not use metazone, just skip this.
- }
- }
+ if (olsonToMeta == null) {
+ // We need to return non-null Map to avoid disaster
+ olsonToMeta = new HashMap();
}
OLSON_TO_META_REF = new SoftReference(olsonToMeta);
}
@@ -814,6 +768,127 @@
return olsonToMeta;
}
+ /*
+ * Create olson tzid to metazone mappings from metazoneInfo.res (3.8.1 or later)
+ */
+ private static Map createOlsonToMetaMap() {
+ // Create olson id to metazone mapping table
+ HashMap olsonToMeta = null;
+ UResourceBundle metazoneMappingsBundle = null;
+ try {
+ UResourceBundle bundle = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "metazoneInfo");
+ metazoneMappingsBundle = bundle.get("metazoneMappings");
+ } catch (MissingResourceException mre) {
+ // do nothing
+ }
+ if (metazoneMappingsBundle != null) {
+ String[] tzids = getAvailableIDs();
+ for (int i = 0; i < tzids.length; i++) {
+ // Skip aliases
+ if (!tzids[i].equals(getCanonicalID(tzids[i]))) {
+ continue;
+ }
+ String tzkey = tzids[i].replace('/', ':');
+ try {
+ UResourceBundle zoneBundle = metazoneMappingsBundle.get(tzkey);
+ LinkedList mzMappings = new LinkedList();
+ for (int idx = 0; ; idx++) {
+ try {
+ UResourceBundle mz = zoneBundle.get("mz" + idx);
+ String[] mzstr = mz.getStringArray();
+ if (mzstr == null || mzstr.length != 3) {
+ continue;
+ }
+ OlsonToMetaMappingEntry mzmap = new OlsonToMetaMappingEntry();
+ mzmap.mzid = mzstr[0].intern();
+ mzmap.from = parseDate(mzstr[1]);
+ mzmap.to = parseDate(mzstr[2]);
+
+ // Add this mapping to the list
+ mzMappings.add(mzmap);
+ } catch (MissingResourceException nomz) {
+ // we're done
+ break;
+ } catch (IllegalArgumentException baddate) {
+ // skip this
+ }
+ }
+ if (mzMappings.size() != 0) {
+ // Add to the olson-to-meta map
+ if (olsonToMeta == null) {
+ olsonToMeta = new HashMap();
+ }
+ olsonToMeta.put(tzids[i], mzMappings);
+ }
+ } catch (MissingResourceException noum) {
+ // Does not use metazone, just skip this.
+ }
+ }
+ }
+ return olsonToMeta;
+ }
+
+ /*
+ * Create olson tzid to metazone mappings from root.res (3.8)
+ */
+ private static Map createOlsonToMetaMapOld() {
+ // Create olson id to metazone mapping table
+ HashMap olsonToMeta = null;
+ UResourceBundle zoneStringsBundle = null;
+ try {
+ UResourceBundle bundle = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "root");
+ zoneStringsBundle = bundle.get("zoneStrings");
+ } catch (MissingResourceException mre) {
+ // do nothing
+ }
+ if (zoneStringsBundle != null) {
+ String[] tzids = getAvailableIDs();
+ for (int i = 0; i < tzids.length; i++) {
+ // Skip aliases
+ if (!tzids[i].equals(getCanonicalID(tzids[i]))) {
+ continue;
+ }
+ String tzkey = tzids[i].replace('/', ':');
+ try {
+ UResourceBundle zoneBundle = zoneStringsBundle.get(tzkey);
+ UResourceBundle useMZ = zoneBundle.get("um");
+ LinkedList mzMappings = new LinkedList();
+ for (int idx = 0; ; idx++) {
+ try {
+ UResourceBundle mz = useMZ.get("mz" + idx);
+ String[] mzstr = mz.getStringArray();
+ if (mzstr == null || mzstr.length != 3) {
+ continue;
+ }
+ OlsonToMetaMappingEntry mzmap = new OlsonToMetaMappingEntry();
+ mzmap.mzid = mzstr[0].intern();
+ mzmap.from = parseDate(mzstr[1]);
+ mzmap.to = parseDate(mzstr[2]);
+
+ // Add this mapping to the list
+ mzMappings.add(mzmap);
+ } catch (MissingResourceException nomz) {
+ // we're done
+ break;
+ } catch (IllegalArgumentException baddate) {
+ // skip this
+ }
+ }
+ if (mzMappings.size() != 0) {
+ // Add to the olson-to-meta map
+ if (olsonToMeta == null) {
+ olsonToMeta = new HashMap();
+ }
+ olsonToMeta.put(tzids[i], mzMappings);
+ }
+ } catch (MissingResourceException noum) {
+ // Does not use metazone, just skip this.
+ }
+ }
+ }
+ return olsonToMeta;
+ }
+
/**
* Returns a CLDR metazone ID for the given Olson tzid and time.
*/
@@ -920,4 +995,67 @@
// }
// return getZoneIdByMetazone(metazoneID, region);
// }
+
+ /*
+ * Convert a date string used by metazone mappings to long.
+ * The format used by CLDR metazone mapping is "yyyy-MM-dd HH:mm".
+ * We do not want to use SimpleDateFormat to parse the metazone
+ * mapping range strings in createOlsonToMeta, because it might be
+ * called from SimpleDateFormat initialization code.
+ */
+ static long parseDate (String text) throws IllegalArgumentException {
+ int year = 0, month = 0, day = 0, hour = 0, min = 0;
+ int idx;
+ int n;
+
+ // "yyyy" (0 - 3)
+ for (idx = 0; idx <= 3; idx++) {
+ n = text.charAt(idx) - '0';
+ if (n >= 0 && n < 10) {
+ year = 10*year + n;
+ } else {
+ throw new IllegalArgumentException("Bad year");
+ }
+ }
+ // "MM" (5 - 6)
+ for (idx = 5; idx <= 6; idx++) {
+ n = text.charAt(idx) - '0';
+ if (n >= 0 && n < 10) {
+ month = 10*month + n;
+ } else {
+ throw new IllegalArgumentException("Bad month");
+ }
+ }
+ // "dd" (8 - 9)
+ for (idx = 8; idx <= 9; idx++) {
+ n = text.charAt(idx) - '0';
+ if (n >= 0 && n < 10) {
+ day = 10*day + n;
+ } else {
+ throw new IllegalArgumentException("Bad day");
+ }
+ }
+ // "HH" (11 - 12)
+ for (idx = 11; idx <= 12; idx++) {
+ n = text.charAt(idx) - '0';
+ if (n >= 0 && n < 10) {
+ hour = 10*hour + n;
+ } else {
+ throw new IllegalArgumentException("Bad hour");
+ }
+ }
+ // "mm" (14 - 15)
+ for (idx = 14; idx <= 15; idx++) {
+ n = text.charAt(idx) - '0';
+ if (n >= 0 && n < 10) {
+ min = 10*min + n;
+ } else {
+ throw new IllegalArgumentException("Bad minute");
+ }
+ }
+
+ long date = Grego.fieldsToDay(year, month - 1, day) * Grego.MILLIS_PER_DAY
+ + hour * Grego.MILLIS_PER_HOUR + min * Grego.MILLIS_PER_MINUTE;
+ return date;
+ }
}
diff --git a/icu4j/src/com/ibm/icu/impl/data/icudata.jar b/icu4j/src/com/ibm/icu/impl/data/icudata.jar
index bcd5c59..414c266 100755
--- a/icu4j/src/com/ibm/icu/impl/data/icudata.jar
+++ b/icu4j/src/com/ibm/icu/impl/data/icudata.jar
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0e01a9a1a779d74792f4ae0391b586695f6dd280d7d972fd1e9919bbe74905fe
-size 5391701
+oid sha256:d50452d34dbff6e92dbe1d2985eb62696e35bafd40914a57afd0ba2edc8c8876
+size 5409244
diff --git a/icu4j/src/com/ibm/icu/text/SimpleDateFormat.java b/icu4j/src/com/ibm/icu/text/SimpleDateFormat.java
index 8edc3df..68752f7 100644
--- a/icu4j/src/com/ibm/icu/text/SimpleDateFormat.java
+++ b/icu4j/src/com/ibm/icu/text/SimpleDateFormat.java
@@ -1648,7 +1648,6 @@
}
} else { // tztype == TZTYPE_DST
if (offsets[1] == 0) {
- int savings = 60*60*1000; // default DST savings
if (btz != null) {
long time = localMillis + offsets[0];
// We use the nearest daylight saving time rule.
@@ -1684,16 +1683,23 @@
if (beforeTrs != null && afterTrs != null) {
if (time - beforeT > afterT - time) {
- savings = afterSav;
+ resolvedSavings = afterSav;
} else {
- savings = beforeSav;
+ resolvedSavings = beforeSav;
}
- } else if (beforeTrs != null) {
- savings = beforeSav;
- } else if (afterTrs != null) {
- savings = afterSav;
+ } else if (beforeTrs != null && beforeSav != 0) {
+ resolvedSavings = beforeSav;
+ } else if (afterTrs != null && afterSav != 0) {
+ resolvedSavings = afterSav;
+ } else {
+ resolvedSavings = btz.getDSTSavings();
}
- resolvedSavings = savings;
+ } else {
+ resolvedSavings = tz.getDSTSavings();
+ }
+ if (resolvedSavings == 0) {
+ // Final fallback
+ resolvedSavings = millisPerHour;
}
}
}
diff --git a/icu4j/src/com/ibm/icu/util/Calendar.java b/icu4j/src/com/ibm/icu/util/Calendar.java
index 8dfcaf9..779b12a 100644
--- a/icu4j/src/com/ibm/icu/util/Calendar.java
+++ b/icu4j/src/com/ibm/icu/util/Calendar.java
@@ -4041,8 +4041,6 @@
fields[JULIAN_DAY] = (int) days + EPOCH_JULIAN_DAY;
- // In some cases we will have to call this method again below to
- // adjust for DST pushing us into the next Julian day.
computeGregorianAndDOWFields(fields[JULIAN_DAY]);
// Call framework method to have subclass compute its fields.