From 11da2bc07350e66268cbf1e3cd6b605bc59ea2e8 Mon Sep 17 00:00:00 2001 From: Andy Heninger Date: Wed, 7 Oct 2015 00:32:46 +0000 Subject: [PATCH] ICU-11619 VTimeZone throws a ClassCastException when Zone ID unknown; move fixes from branch to trunk. X-SVN-Rev: 38039 --- .../core/src/com/ibm/icu/impl/ZoneMeta.java | 8 ++-- .../core/src/com/ibm/icu/util/TimeZone.java | 48 ++++++++++--------- .../core/src/com/ibm/icu/util/VTimeZone.java | 8 +++- .../icu/dev/test/timezone/TimeZoneTest.java | 5 ++ 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/ZoneMeta.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/ZoneMeta.java index 177206b90d3..b89bbf9eda7 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/ZoneMeta.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/ZoneMeta.java @@ -1,6 +1,6 @@ /* ********************************************************************** -* Copyright (c) 2003-2014 International Business Machines +* Copyright (c) 2003-2015 International Business Machines * Corporation and others. All Rights Reserved. ********************************************************************** * Author: Alan Liu @@ -571,7 +571,7 @@ public final class ZoneMeta { * Returns a frozen OlsonTimeZone instance for the given ID. * This method returns null when the given ID is unknown. */ - public static TimeZone getSystemTimeZone(String id) { + public static OlsonTimeZone getSystemTimeZone(String id) { return SYSTEM_ZONE_CACHE.getInstance(id, id); } @@ -612,7 +612,7 @@ public final class ZoneMeta { * @return a frozen SimpleTimeZone with the given offset and * no Daylight Savings Time, or null if the id cannot be parsed. */ - public static TimeZone getCustomTimeZone(String id){ + public static SimpleTimeZone getCustomTimeZone(String id){ int[] fields = new int[4]; if (parseCustomID(id, fields)) { // fields[0] - sign @@ -769,7 +769,7 @@ public final class ZoneMeta { * @param offset GMT offset in milliseconds * @return A custom TimeZone for the offset with normalized time zone id */ - public static TimeZone getCustomTimeZone(int offset) { + public static SimpleTimeZone getCustomTimeZone(int offset) { boolean negative = false; int tmp = offset; if (offset < 0) { diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/TimeZone.java b/icu4j/main/classes/core/src/com/ibm/icu/util/TimeZone.java index 421ed136cc7..b441c8eaad4 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/util/TimeZone.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/util/TimeZone.java @@ -740,45 +740,47 @@ abstract public class TimeZone implements Serializable, Cloneable, FreezableTimeZone for the given ID and the timezone type. - * @param ID time zone ID + * @param id time zone ID * @param type time zone implementation type, TIMEZONE_JDK or TIMEZONE_ICU * @param frozen specify if the returned object can be frozen * @return the specified TimeZone or UNKNOWN_ZONE if the given ID * cannot be understood. */ - private static TimeZone getTimeZone(String ID, int type, boolean frozen) { + private static TimeZone getTimeZone(String id, int type, boolean frozen) { TimeZone result; if (type == TIMEZONE_JDK) { - result = JavaTimeZone.createTimeZone(ID); + result = JavaTimeZone.createTimeZone(id); if (result != null) { return frozen ? result.freeze() : result; - } + } + result = getFrozenICUTimeZone(id, false); } 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); + result = getFrozenICUTimeZone(id, true); } - if (result == null) { - LOGGER.fine("\"" +ID + "\" is a bogus id so timezone is falling back to Etc/Unknown(GMT)."); + LOGGER.fine("\"" +id + "\" is a bogus id so timezone is falling back to Etc/Unknown(GMT)."); result = UNKNOWN_ZONE; } - return frozen ? result : result.cloneAsThawed(); } + + /** + * Returns a frozen ICU type TimeZone object given a time zone ID. + * @param id the time zone ID + * @param trySystem if true tries the system time zones first otherwise skip to the + * custom time zones. + * @return the frozen ICU TimeZone or null if one could not be created. + */ + static BasicTimeZone getFrozenICUTimeZone(String id, boolean trySystem) { + BasicTimeZone result = null; + if (trySystem) { + result = ZoneMeta.getSystemTimeZone(id); + } + if (result == null) { + result = ZoneMeta.getCustomTimeZone(id); + } + return result; + } /** * Sets the default time zone type used by getTimeZone. diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/VTimeZone.java b/icu4j/main/classes/core/src/com/ibm/icu/util/VTimeZone.java index bcfbec2d778..3aeed4aa162 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/util/VTimeZone.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/util/VTimeZone.java @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 2007-2014, International Business Machines Corporation and * + * Copyright (C) 2007-2015, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -47,8 +47,12 @@ public class VTimeZone extends BasicTimeZone { * @stable ICU 3.8 */ public static VTimeZone create(String tzid) { + BasicTimeZone basicTimeZone = TimeZone.getFrozenICUTimeZone(tzid, true); + if (basicTimeZone == null) { + return null; + } VTimeZone vtz = new VTimeZone(tzid); - vtz.tz = (BasicTimeZone)TimeZone.getTimeZone(tzid, TimeZone.TIMEZONE_ICU); + vtz.tz = (BasicTimeZone) basicTimeZone.cloneAsThawed(); vtz.olsonzid = vtz.tz.getID(); return vtz; diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java index ee9d5e7e8ad..bc644726ed6 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java @@ -2179,6 +2179,11 @@ public class TimeZoneTest extends TestFmwk } } } + + public void Test11619_UnrecognizedTimeZoneID() { + VTimeZone vzone = VTimeZone.create("ABadTimeZoneId"); + this.assertNull("", vzone); + } private static boolean isDaylightTimeAvailable(TimeZone tz, long start) { if (tz.inDaylightTime(new Date(start))) { -- 2.40.0