]> granicus.if.org Git - icu/commitdiff
ICU-9867 New time zone pattern letters/types spport for CLDR 23/ICU 51.
authorYoshito Umaoka <y.umaoka@gmail.com>
Sun, 10 Feb 2013 17:26:01 +0000 (17:26 +0000)
committerYoshito Umaoka <y.umaoka@gmail.com>
Sun, 10 Feb 2013 17:26:01 +0000 (17:26 +0000)
X-SVN-Rev: 33157

13 files changed:
icu4j/main/classes/core/src/com/ibm/icu/impl/TimeZoneNamesImpl.java
icu4j/main/classes/core/src/com/ibm/icu/impl/ZoneMeta.java
icu4j/main/classes/core/src/com/ibm/icu/text/DateFormat.java
icu4j/main/classes/core/src/com/ibm/icu/text/DateFormatSymbols.java
icu4j/main/classes/core/src/com/ibm/icu/text/SimpleDateFormat.java
icu4j/main/classes/core/src/com/ibm/icu/text/TimeZoneFormat.java
icu4j/main/classes/core/src/com/ibm/icu/text/TimeZoneNames.java
icu4j/main/classes/core/src/com/ibm/icu/util/TimeZone.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateFormatTest.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateIntervalFormatTest.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/TimeZoneFormatTest.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneRegression.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java

index e2e06a58e64d9fdeff54923dc25384ad59b2d7bb..c9c0de9d3cb5e850c6030401512e990f756fd1fd 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *******************************************************************************
- * Copyright (C) 2011, International Business Machines Corporation and         *
+ * Copyright (C) 2011-2013, International Business Machines Corporation and    *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  */
@@ -22,6 +22,7 @@ import java.util.Map;
 import java.util.MissingResourceException;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Pattern;
 
 import com.ibm.icu.impl.TextTrieMap.ResultHandler;
 import com.ibm.icu.text.TimeZoneNames;
@@ -164,10 +165,7 @@ public class TimeZoneNamesImpl extends TimeZoneNames {
         if (tzID == null || tzID.length() == 0) {
             return null;
         }
-        String locName = loadTimeZoneNames(tzID).getLocationName();
-        if (locName == null) {
-            locName = super.getExemplarLocationName(tzID);
-        }
+        String locName = loadTimeZoneNames(tzID).getName(NameType.EXEMPLAR_LOCATION);
         return locName;
     }
 
@@ -303,7 +301,7 @@ public class TimeZoneNamesImpl extends TimeZoneNames {
     private synchronized TZNames loadTimeZoneNames(String tzID) {
         TZNames tznames = _tzNamesMap.get(tzID);
         if (tznames == null) {
-            tznames = TZNames.getInstance(_zoneStrings, tzID.replace('/', ':'));
+            tznames = TZNames.getInstance(_zoneStrings, tzID.replace('/', ':'), tzID);
             // put names into the trie
             tzID = tzID.intern();
             for (NameType t : NameType.values()) {
@@ -442,6 +440,9 @@ public class TimeZoneNamesImpl extends TimeZoneNames {
             case SHORT_DAYLIGHT:
                 name = _names[5];
                 break;
+            case EXEMPLAR_LOCATION:
+                name = null;    // implemented by subclass
+                break;
             }
 
             return name;
@@ -486,26 +487,25 @@ public class TimeZoneNamesImpl extends TimeZoneNames {
 
         private static final TZNames EMPTY_TZNAMES = new TZNames(null, null);
 
-        public static TZNames getInstance(ICUResourceBundle zoneStrings, String key) {
+        public static TZNames getInstance(ICUResourceBundle zoneStrings, String key, String tzID) {
             if (zoneStrings == null || key == null || key.length() == 0) {
                 return EMPTY_TZNAMES;
             }
 
+            String[] names = loadData(zoneStrings, key);
+            String locationName = null;
+
             ICUResourceBundle table = null;
             try {
                 table = zoneStrings.getWithFallback(key);
-            } catch (MissingResourceException e) {
-                return EMPTY_TZNAMES;
-            }
-
-            String locationName = null;
-            try {
                 locationName = table.getStringWithFallback("ec");
             } catch (MissingResourceException e) {
-                // location name is optional
+                // fall through
             }
 
-            String[] names = loadData(zoneStrings, key);
+            if (locationName == null) {
+                locationName = getDefaultExemplarLocationName(tzID);
+            }
 
             if (locationName == null && names == null) {
                 return EMPTY_TZNAMES;
@@ -513,8 +513,11 @@ public class TimeZoneNamesImpl extends TimeZoneNames {
             return new TZNames(names, locationName);
         }
 
-        public String getLocationName() {
-            return _locationName;
+        public String getName(NameType type) {
+            if (type == NameType.EXEMPLAR_LOCATION) {
+                return _locationName;
+            }
+            return super.getName(type);
         }
 
         private TZNames(String[] names, String locationName) {
@@ -686,4 +689,25 @@ public class TimeZoneNamesImpl extends TimeZoneNames {
             return map;
         }
     }
+
+    private static final Pattern LOC_EXCLUSION_PATTERN = Pattern.compile("Etc/.*|SystemV/.*|.*/Riyadh8[7-9]");
+
+    /**
+     * Default exemplar location name based on time zone ID
+     * @param tzID the time zone ID
+     * @return the exemplar location name or null if location is not available.
+     */
+    public static String getDefaultExemplarLocationName(String tzID) {
+        if (tzID == null || tzID.length() == 0 || LOC_EXCLUSION_PATTERN.matcher(tzID).matches()) {
+            return null;
+        }
+
+        String location = null;
+        int sep = tzID.lastIndexOf('/');
+        if (sep > 0 && sep + 1 < tzID.length()) {
+            location = tzID.substring(sep + 1).replace('_', ' ');
+        }
+
+        return location;
+    }
 }
index f0cc3c5f2deec1536e805fb1dd21825765b79208..bd18c0454d3244bde4963c4ae32404b4012e6700 100644 (file)
@@ -829,4 +829,56 @@ public final class ZoneMeta {
         }
         return zid.toString();
     }
+
+    /**
+     * Returns the time zone's short ID for the zone.
+     * For example, "uslax" for zone "America/Los_Angeles".
+     * @param tz the time zone
+     * @return the short ID of the time zone, or null if the short ID is not available.
+     */
+    public static String getShortID(TimeZone tz) {
+        String canonicalID = null;
+
+        if (tz instanceof OlsonTimeZone) {
+            canonicalID = ((OlsonTimeZone)tz).getCanonicalID();
+        }
+        canonicalID = getCanonicalCLDRID(tz.getID());
+        if (canonicalID == null) {
+            return null;
+        }
+        return getShortIDFromCanonical(canonicalID);
+    }
+
+    /**
+     * Returns the time zone's short ID for the zone ID.
+     * For example, "uslax" for zone ID "America/Los_Angeles".
+     * @param id the time zone ID
+     * @return the short ID of the time zone ID, or null if the short ID is not available.
+     */
+    public static String getShortID(String id) {
+        String canonicalID = getCanonicalCLDRID(id);
+        if (canonicalID == null) {
+            return null;
+        }
+        return getShortIDFromCanonical(canonicalID);
+    }
+
+    private static String getShortIDFromCanonical(String canonicalID) {
+        String shortID = null;
+        String tzidKey = canonicalID.replace('/', ':');
+
+        try {
+            // First, try check if the given ID is canonical
+            UResourceBundle keyTypeData = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,
+                    "keyTypeData", ICUResourceBundle.ICU_DATA_CLASS_LOADER);
+            UResourceBundle typeMap = keyTypeData.get("typeMap");
+            UResourceBundle typeKeys = typeMap.get("timezone");
+            shortID = typeKeys.getString(tzidKey);
+        } catch (MissingResourceException e) {
+            // fall through
+        }
+
+        return shortID;
+    }
+
 }
index b7a6d66b8ba5ec211f82338232e49209ff34b9ff..dd3533c4c1d6b6a685204053e0e8dda2c4e764e1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) 1996-2012, International Business Machines
+ *   Copyright (C) 1996-2013, International Business Machines
  *   Corporation and others.  All Rights Reserved.
  */
 
@@ -407,12 +407,43 @@ public abstract class DateFormat extends UFormat {
      */
     public final static int YEAR_NAME_FIELD = 30;
 
+    /**
+     * {@icu} FieldPosition selector for 'O' field alignment,
+     * corresponding to the {@link Calendar#ZONE_OFFSET} and
+     * {@link Calendar#DST_OFFSET} fields.  This displays the
+     * localized GMT format.
+     * @draft ICU 51
+     * @provisional This API might change or be removed in a future release.
+     */
+    public final static int TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD = 31;
+
+    /**
+     * {@icu} FieldPosition selector for 'X' field alignment,
+     * corresponding to the {@link Calendar#ZONE_OFFSET} and
+     * {@link Calendar#DST_OFFSET} fields.  This displays the
+     * ISO 8601 local time offset format or UTC indicator ("Z").
+     * @draft ICU 51
+     * @provisional This API might change or be removed in a future release.
+     */
+    public final static int TIMEZONE_ISO_FIELD = 32;
+
+    /**
+     * {@icu} FieldPosition selector for 'x' field alignment,
+     * corresponding to the {@link Calendar#ZONE_OFFSET} and
+     * {@link Calendar#DST_OFFSET} fields.  This displays the
+     * ISO 8601 local time offset format.
+     * @draft ICU 51
+     * @provisional This API might change or be removed in a future release.
+     */
+    public final static int TIMEZONE_ISO_LOCAL_FIELD = 33;
+
     /**
      * {@icu} Number of FieldPosition selectors for DateFormat.
      * Valid selectors range from 0 to FIELD_COUNT-1.
      * @stable ICU 3.0
      */
-    public final static int FIELD_COUNT = 31; // must == DateFormatSymbols.patternChars.length()
+
+    public final static int FIELD_COUNT = 34; // must == DateFormatSymbols.patternChars.length()
 
     // Proclaim serial compatibility with 1.1 FCS
     private static final long serialVersionUID = 7218322306649953788L;
index 657c6b98bc8cb5bd4fb7a91c9d6bac8ad0680051..f679debb7f2810ad6c43fd0b8c6840143022fd84 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *******************************************************************************
- * Copyright (C) 1996-2012, International Business Machines Corporation and    *
+ * Copyright (C) 1996-2013, International Business Machines Corporation and    *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  */
@@ -514,7 +514,7 @@ public class DateFormatSymbols implements Serializable, Cloneable {
      * Unlocalized date-time pattern characters. For example: 'y', 'd', etc.
      * All locales use the same unlocalized pattern characters.
      */
-    static final String  patternChars = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVU";
+    static final String  patternChars = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXx";
 
     /**
      * Localized date-time pattern characters. For example, a locale may
index 15678b770feb59b65d07f28b54dd1104cd4dd8d9..6819f2e3ade995fb297641a6215dc40e6ec57ab1 100644 (file)
@@ -98,8 +98,13 @@ import com.ibm.icu.util.ULocale.Category;
  * ZZZZZ    time zone (ISO 8601)    (Text & Number)     -08:00 & Z (UTC)
  * v        time zone (generic)     (Text)              PT
  * vvvv     time zone (generic)     (Text)              Pacific Time
- * V        time zone (abreviation) (Text)              PST
- * VVVV     time zone (location)    (Text)              United States Time (Los Angeles)
+ * V        time zone (short ID)    (Text)              uslax
+ * VV       time zone (ID)          (Text)              America/Los_Angeles
+ * VVV      time zone (exemplar)    (Text)              Los Angeles
+ * VVVV     time zone (location)    (Text)              Los Angeles Time
+ * O        time zone (GMT offset)  (Text & Number)     GMT-8 & GMT-08:00
+ * X        time zone (ISO 8601)    (Text & Number)     -08, -0800, -08:00 & Z (UTC)
+ * x        time zone (ISO 8601)    (Number)            -08, -0800 & -08:00
  * g*       Julian day              (Number)            2451334
  * A*       milliseconds in day     (Number)            69540000
  * Q*       quarter in year         (Text & Number)     Q1 & 01
@@ -274,14 +279,14 @@ public class SimpleDateFormat extends DateFormat {
      */
     private static final int[] PATTERN_CHAR_TO_LEVEL =
     {
-    //       A   B   C   D    E   F   G    H   I   J   K   L    M   N   O
-        -1, 40, -1, -1, 20,  30, 30,  0,  50, -1, -1, 50, 20,  20, -1, -1,
-    //   P   Q   R    S   T   U  V   W   X   Y  Z
-        -1, 20, -1,  80, -1, 10, 0, 30, -1, 10, 0, -1, -1, -1, -1, -1,
-    //       a   b   c   d    e   f  g   h   i   j    k   l    m   n   o
-        -1, 40, -1, 30,  30, 30, -1, 0, 50, -1, -1,  50, -1,  60, -1, -1,
-    //   p   q   r    s   t   u  v   w   x    y  z
-        -1, 20, -1,  70, -1, 10, 0, 20, -1,  10, 0, -1, -1, -1, -1, -1
+    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
+        -1, 40, -1, -1, 20, 30, 30,  0, 50, -1, -1, 50, 20, 20, -1,  0,
+    //   P   Q   R   S   T   U   V   W   X   Y   Z
+        -1, 20, -1, 80, -1, 10,  0, 30,  0, 10,  0, -1, -1, -1, -1, -1,
+    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
+        -1, 40, -1, 30, 30, 30, -1,  0, 50, -1, -1, 50, -1, 60, -1, -1,
+    //   p   q   r   s   t   u   v   w   x   y   z
+        -1, 20, -1, 70, -1, 10,  0, 20,  0, 10,  0, -1, -1, -1, -1, -1
     };
 
     // When calendar uses hebr numbering (i.e. he@calendar=hebrew),
@@ -798,13 +803,13 @@ public class SimpleDateFormat extends DateFormat {
     private static final int[] PATTERN_CHAR_TO_INDEX =
     {
     //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
-        -1, 22, -1, -1, 10,  9, 11,  0,  5, -1, -1, 16, 26,  2, -1, -1,
+        -1, 22, -1, -1, 10,  9, 11,  0,  5, -1, -1, 16, 26,  2, -1, 31,
     //   P   Q   R   S   T   U   V   W   X   Y   Z
-        -1, 27, -1,  8, -1, 30, 29, 13, -1, 18, 23, -1, -1, -1, -1, -1,
+        -1, 27, -1,  8, -1, 30, 29, 13, 32, 18, 23, -1, -1, -1, -1, -1,
     //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
         -1, 14, -1, 25,  3, 19, -1, 21, 15, -1, -1,  4, -1,  6, -1, -1,
     //   p   q   r   s   t   u   v   w   x   y   z
-        -1, 28, -1,  7, -1, 20, 24, 12, -1,  1, 17, -1, -1, -1, -1, -1
+        -1, 28, -1,  7, -1, 20, 24, 12, 33,  1, 17, -1, -1, -1, -1, -1
     };
 
     // Map pattern character index to Calendar field number
@@ -824,6 +829,8 @@ public class SimpleDateFormat extends DateFormat {
         /*Qq*/  Calendar.MONTH, Calendar.MONTH,
         /*V*/   Calendar.ZONE_OFFSET,
         /*U*/   Calendar.YEAR,
+        /*O*/   Calendar.ZONE_OFFSET,
+        /*Xx*/  Calendar.ZONE_OFFSET, Calendar.ZONE_OFFSET,
     };
 
     // Map pattern character index to DateFormat field number
@@ -842,6 +849,8 @@ public class SimpleDateFormat extends DateFormat {
         /*Qq*/  DateFormat.QUARTER_FIELD, DateFormat.STANDALONE_QUARTER_FIELD,
         /*V*/   DateFormat.TIMEZONE_SPECIAL_FIELD,
         /*U*/   DateFormat.YEAR_NAME_FIELD,
+        /*O*/   DateFormat.TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD,
+        /*Xx*/  DateFormat.TIMEZONE_ISO_FIELD, DateFormat.TIMEZONE_ISO_LOCAL_FIELD,
     };
 
     // Map pattern character index to DateFormat.Field
@@ -860,6 +869,8 @@ public class SimpleDateFormat extends DateFormat {
         /*Qq*/  DateFormat.Field.QUARTER, DateFormat.Field.QUARTER,
         /*V*/   DateFormat.Field.TIME_ZONE,
         /*U*/   DateFormat.Field.YEAR,
+        /*O*/   DateFormat.Field.TIME_ZONE,
+        /*Xx*/  DateFormat.Field.TIME_ZONE, DateFormat.Field.TIME_ZONE,
     };
 
     /**
@@ -1114,7 +1125,8 @@ public class SimpleDateFormat extends DateFormat {
                 zeroPaddingNumber(currentNumberFormat,buf, value, count, maxIntCount);
             }
             break;
-        case 17: // 'z' - ZONE_OFFSET
+
+        case 17: // 'z' - TIMEZONE_FIELD
             if (count < 4) {
                 // "z", "zz", "zzz"
                 result = tzFormat().format(Style.SPECIFIC_SHORT, tz, date);
@@ -1125,22 +1137,20 @@ public class SimpleDateFormat extends DateFormat {
             }
             buf.append(result);
             break;
-        case 23: // 'Z' - TIMEZONE_RFC
-        {
+        case 23: // 'Z' - TIMEZONE_RFC_FIELD
             if (count < 4) {
-                // RFC822 format
-                result = tzFormat().format(Style.RFC822, tz, date);
+                // RFC822 format - equivalent to ISO 8601 local offset fixed width format
+                result = tzFormat().format(Style.ISO_BASIC_LOCAL_FULL, tz, date);
             } else if (count == 5) {
                 // ISO 8601 extended format
-                result = tzFormat().format(Style.ISO8601, tz, date);
+                result = tzFormat().format(Style.ISO_EXTENDED_FULL, tz, date);
             } else {
                 // long form, localized GMT pattern
                 result = tzFormat().format(Style.LOCALIZED_GMT, tz, date);
             }
                 buf.append(result);
             break;
-            }
-        case 24: // 'v' - TIMEZONE_GENERIC
+        case 24: // 'v' - TIMEZONE_GENERIC_FIELD
             if (count == 1) {
                 // "v"
                 result = tzFormat().format(Style.GENERIC_SHORT, tz, date);
@@ -1149,7 +1159,72 @@ public class SimpleDateFormat extends DateFormat {
                 // "vvvv"
                 result = tzFormat().format(Style.GENERIC_LONG, tz, date);
                 capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.METAZONE_LONG;
-           }
+            }
+            buf.append(result);
+            break;
+        case 29: // 'V' - TIMEZONE_SPECIAL_FIELD
+            if (count == 1) {
+                // "V"
+                result = tzFormat().format(Style.ZONE_ID_SHORT, tz, date);
+            } else if (count == 2) {
+                // "VV"
+                result = tzFormat().format(Style.ZONE_ID, tz, date);
+            } else if (count == 3) {
+                // "VVV"
+                result = tzFormat().format(Style.EXEMPLAR_LOCATION, tz, date);
+            } else if (count == 4) {
+                // "VVVV"
+                result = tzFormat().format(Style.GENERIC_LOCATION, tz, date);
+                capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.ZONE_LONG;
+            }
+            buf.append(result);
+            break;
+        case 31: // 'O' - TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD
+            if (count == 1) {
+                // "O" - Short Localized GMT format
+                result = tzFormat().format(Style.LOCALIZED_GMT_SHORT, tz, date);
+            } else if (count == 4) {
+                // "OOOO" - Localized GMT format
+                result = tzFormat().format(Style.LOCALIZED_GMT, tz, date);
+            }
+            buf.append(result);
+            break;
+        case 32: // 'X' - TIMEZONE_ISO_FIELD
+            if (count == 1) {
+                // "X" - ISO Basic/Short
+                result = tzFormat().format(Style.ISO_BASIC_SHORT, tz, date);
+            } else if (count == 2) {
+                // "XX" - ISO Basic/Fixed
+                result = tzFormat().format(Style.ISO_BASIC_FIXED, tz, date);
+            } else if (count == 3) {
+                // "XXX" - ISO Extended/Fixed
+                result = tzFormat().format(Style.ISO_EXTENDED_FIXED, tz, date);
+            } else if (count == 4) {
+                // "XXXX" - ISO Basic/Optional second field
+                result = tzFormat().format(Style.ISO_BASIC_FULL, tz, date);
+            } else if (count == 5) {
+                // "XXXXX" - ISO Extended/Optional second field
+                result = tzFormat().format(Style.ISO_EXTENDED_FULL, tz, date);
+            }
+            buf.append(result);
+            break;
+        case 33: // 'x' - TIMEZONE_ISO_LOCAL_FIELD
+            if (count == 1) {
+                // "x" - ISO Local Basic/Short
+                result = tzFormat().format(Style.ISO_BASIC_LOCAL_SHORT, tz, date);
+            } else if (count == 2) {
+                // "x" - ISO Local Basic/Fixed
+                result = tzFormat().format(Style.ISO_BASIC_LOCAL_FIXED, tz, date);
+            } else if (count == 3) {
+                // "xxx" - ISO Local Extended/Fixed
+                result = tzFormat().format(Style.ISO_EXTENDED_LOCAL_FIXED, tz, date);
+            } else if (count == 4) {
+                // "xxxx" - ISO Local Basic/Optional second field
+                result = tzFormat().format(Style.ISO_BASIC_LOCAL_FULL, tz, date);
+            } else if (count == 5) {
+                // "xxxxx" - ISO Local Extended/Optional second field
+                result = tzFormat().format(Style.ISO_EXTENDED_LOCAL_FULL, tz, date);
+            }
             buf.append(result);
             break;
 
@@ -1190,18 +1265,6 @@ public class SimpleDateFormat extends DateFormat {
                 zeroPaddingNumber(currentNumberFormat,buf, (value/3)+1, count, maxIntCount);
             }
             break;
-        case 29: // 'V' - TIMEZONE_SPECIAL
-            if (count == 1) {
-                // "V"
-                result = tzFormat().format(Style.SPECIFIC_SHORT, tz, date);
-                capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.METAZONE_SHORT;
-            } else if (count == 4) {
-                // "VVVV"
-                result = tzFormat().format(Style.GENERIC_LOCATION, tz, date);
-                capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.ZONE_LONG;
-            }
-            buf.append(result);
-            break;
         default:
             // case 3: // 'd' - DATE
             // case 5: // 'H' - HOUR_OF_DAY (0..23)
@@ -2409,11 +2472,11 @@ public class SimpleDateFormat extends DateFormat {
                     return pos.getIndex();
                 }
                 return -start;
-                    }
+            }
             case 23: // 'Z' - TIMEZONE_RFC
             {
                 Output<TimeType> tzTimeType = new Output<TimeType>();
-                Style style = (count < 4) ? Style.RFC822 : ((count == 5) ? Style.ISO8601 : Style.LOCALIZED_GMT);
+                Style style = (count < 4) ? Style.ISO_BASIC_LOCAL_FULL : ((count == 5) ? Style.ISO_EXTENDED_FULL : Style.LOCALIZED_GMT);
                 TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType);
                 if (tz != null) {
                     tztype = tzTimeType.value;
@@ -2438,8 +2501,91 @@ public class SimpleDateFormat extends DateFormat {
             case 29: // 'V' - TIMEZONE_SPECIAL
             {
                 Output<TimeType> tzTimeType = new Output<TimeType>();
-                // Note: 'v' only supports count 1 and 4
-                Style style = (count < 4) ? Style.SPECIFIC_SHORT : Style.GENERIC_LOCATION;
+                Style style = null;
+                switch (count) {
+                case 1:
+                    style = Style.ZONE_ID_SHORT;
+                    break;
+                case 2:
+                    style = Style.ZONE_ID;
+                    break;
+                case 3:
+                    style = Style.EXEMPLAR_LOCATION;
+                    break;
+                default:
+                    style = Style.GENERIC_LOCATION;
+                    break;
+                }
+                TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType);
+                if (tz != null) {
+                    tztype = tzTimeType.value;
+                    cal.setTimeZone(tz);
+                    return pos.getIndex();
+                }
+                return -start;
+            }
+            case 31: // 'O' - TIMEZONE_LOCALIZED_GMT_OFFSET
+            {
+                Output<TimeType> tzTimeType = new Output<TimeType>();
+                Style style = (count < 4) ? Style.LOCALIZED_GMT_SHORT : Style.LOCALIZED_GMT;
+                TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType);
+                if (tz != null) {
+                    tztype = tzTimeType.value;
+                    cal.setTimeZone(tz);
+                    return pos.getIndex();
+                }
+                return -start;
+            }
+            case 32: // 'X' - TIMEZONE_ISO
+            {
+                Output<TimeType> tzTimeType = new Output<TimeType>();
+                Style style;
+                switch (count) {
+                case 1:
+                    style = Style.ISO_BASIC_SHORT;
+                    break;
+                case 2:
+                    style = Style.ISO_BASIC_FIXED;
+                    break;
+                case 3:
+                    style = Style.ISO_EXTENDED_FIXED;
+                    break;
+                case 4:
+                    style = Style.ISO_BASIC_FULL;
+                    break;
+                default: // count >= 5
+                    style = Style.ISO_EXTENDED_FULL;
+                    break;
+                }
+                TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType);
+                if (tz != null) {
+                    tztype = tzTimeType.value;
+                    cal.setTimeZone(tz);
+                    return pos.getIndex();
+                }
+                return -start;
+            }
+            case 33: // 'x' - TIMEZONE_ISO_LOCAL
+            {
+                Output<TimeType> tzTimeType = new Output<TimeType>();
+                Style style;
+                switch (count) {
+                case 1:
+                    style = Style.ISO_BASIC_LOCAL_SHORT;
+                    break;
+                case 2:
+                    style = Style.ISO_BASIC_LOCAL_FIXED;
+                    break;
+                case 3:
+                    style = Style.ISO_EXTENDED_LOCAL_FIXED;
+                    break;
+                case 4:
+                    style = Style.ISO_BASIC_LOCAL_FULL;
+                    break;
+                default: // count >= 5
+                    style = Style.ISO_EXTENDED_LOCAL_FULL;
+                    break;
+                }
                 TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType);
                 if (tz != null) {
                     tztype = tzTimeType.value;
index d02b8ded4910c7455bd05c07fc9439b6221053d1..0c8fab61f213ed87b59b57d7a60e9c1fdb335f59 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *******************************************************************************
- * Copyright (C) 2011-2012, International Business Machines Corporation and    *
+ * Copyright (C) 2011-2013, International Business Machines Corporation and    *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  */
@@ -22,11 +22,14 @@ import java.util.BitSet;
 import java.util.Collection;
 import java.util.Date;
 import java.util.EnumSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.MissingResourceException;
+import java.util.Set;
 
 import com.ibm.icu.impl.ICUResourceBundle;
 import com.ibm.icu.impl.SoftCache;
+import com.ibm.icu.impl.TextTrieMap;
 import com.ibm.icu.impl.TimeZoneGenericNames;
 import com.ibm.icu.impl.TimeZoneGenericNames.GenericMatchInfo;
 import com.ibm.icu.impl.TimeZoneGenericNames.GenericNameType;
@@ -39,6 +42,7 @@ import com.ibm.icu.util.Calendar;
 import com.ibm.icu.util.Freezable;
 import com.ibm.icu.util.Output;
 import com.ibm.icu.util.TimeZone;
+import com.ibm.icu.util.TimeZone.SystemTimeZoneType;
 import com.ibm.icu.util.ULocale;
 
 /**
@@ -61,6 +65,9 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
 
     private static final long serialVersionUID = 2281246852693575022L;
 
+    private static final int ISO_Z_STYLE_FLAG = 0x0080;
+    private static final int ISO_LOCAL_STYLE_FLAG = 0x0100;
+
     /**
      * Time zone display format style enum used by format/parse APIs in <code>TimeZoneFormat</code>.
      * 
@@ -72,53 +79,152 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
      */
     public enum Style {
         /**
-         * Generic location format, such as "United States Time (New York)", "Italy Time"
+         * Generic location format, such as "United States Time (New York)" and "Italy Time".
+         * This style is equivalent to the LDML date format pattern "VVVV".
          * @draft ICU 49
          * @provisional This API might change or be removed in a future release.
          */
         GENERIC_LOCATION (0x0001),
         /**
          * Generic long non-location format, such as "Eastern Time".
+         * This style is equivalent to the LDML date format pattern "vvvv".
          * @draft ICU 49
          * @provisional This API might change or be removed in a future release.
          */
         GENERIC_LONG (0x0002),
         /**
          * Generic short non-location format, such as "ET".
+         * This style is equivalent to the LDML date format pattern "v".
          * @draft ICU 49
          * @provisional This API might change or be removed in a future release.
          */
         GENERIC_SHORT (0x0004),
         /**
          * Specific long format, such as "Eastern Standard Time".
+         * This style is equivalent to the LDML date format pattern "zzzz".
          * @draft ICU 49
          * @provisional This API might change or be removed in a future release.
          */
         SPECIFIC_LONG (0x0008),
         /**
          * Specific short format, such as "EST", "PDT".
+         * This style is equivalent to the LDML date format pattern "z".
          * @draft ICU 49
          * @provisional This API might change or be removed in a future release.
          */
         SPECIFIC_SHORT (0x0010),
         /**
-         * RFC822 format, such as "-0500"
+         * Localized GMT offset format, such as "GMT-05:00", "UTC+0100"
+         * This style is equivalent to the LDML date format pattern "OOOO" and "ZZZZ"
          * @draft ICU 49
          * @provisional This API might change or be removed in a future release.
          */
-        RFC822 (0x0020),
+        LOCALIZED_GMT (0x0020),
         /**
-         * Localized GMT offset format, such as "GMT-05:00", "UTC+0100"
-         * @draft ICU 49
+         * Short localized GMT offset format, such as "GMT-5", "UTC+1:30"
+         * This style is equivalent to the LDML date format pattern "O".
+         * @draft ICU 51
          * @provisional This API might change or be removed in a future release.
          */
-        LOCALIZED_GMT (0x0040),
+        LOCALIZED_GMT_SHORT (0x0040),
         /**
-         * ISO 8601 format (extended), such as "-05:00", "Z"(UTC)
-         * @draft ICU 49
+         * Short ISO 8601 local time difference (basic format) or the UTC indicator.
+         * For example, "-05", "+0530", and "Z"(UTC).
+         * This style is equivalent to the LDML date format pattern "X".
+         * @draft ICU 51
+         * @provisional This API might change or be removed in a future release.
+         */
+        ISO_BASIC_SHORT (ISO_Z_STYLE_FLAG),
+        /**
+         * Short ISO 8601 locale time difference (basic format).
+         * For example, "-05" and "+0530".
+         * This style is equivalent to the LDML date format pattern "x".
+         * @draft ICU 51
+         * @provisional This API might change or be removed in a future release.
+         */
+        ISO_BASIC_LOCAL_SHORT (ISO_LOCAL_STYLE_FLAG),
+        /**
+         * Fixed width ISO 8601 local time difference (basic format) or the UTC indicator.
+         * For example, "-0500", "+0530", and "Z"(UTC).
+         * This style is equivalent to the LDML date format pattern "XX".
+         * @draft ICU 51
+         * @provisional This API might change or be removed in a future release.
+         */
+        ISO_BASIC_FIXED (ISO_Z_STYLE_FLAG),
+        /**
+         * Fixed width ISO 8601 local time difference (basic format).
+         * For example, "-0500" and "+0530".
+         * This style is equivalent to the LDML date format pattern "xx".
+         * @draft ICU 51
+         * @provisional This API might change or be removed in a future release.
+         */
+        ISO_BASIC_LOCAL_FIXED (ISO_LOCAL_STYLE_FLAG),
+        /**
+         * ISO 8601 local time difference (basic format) with optional seconds field, or the UTC indicator.
+         * For example, "-0500", "+052538", and "Z"(UTC).
+         * This style is equivalent to the LDML date format pattern "XXXX".
+         * @draft ICU 51
+         * @provisional This API might change or be removed in a future release.
+         */
+        ISO_BASIC_FULL (ISO_Z_STYLE_FLAG),
+        /**
+         * ISO 8601 local time difference (basic format) with optional seconds field.
+         * For example, "-0500" and "+052538".
+         * This style is equivalent to the LDML date format pattern "xxxx".
+         * @draft ICU 51
+         * @provisional This API might change or be removed in a future release.
+         */
+        ISO_BASIC_LOCAL_FULL (ISO_LOCAL_STYLE_FLAG),
+        /**
+         * Fixed width ISO 8601 local time difference (extended format) or the UTC indicator.
+         * For example, "-05:00", "+05:30", and "Z"(UTC).
+         * This style is equivalent to the LDML date format pattern "XXX".
+         * @draft ICU 51
          * @provisional This API might change or be removed in a future release.
          */
-        ISO8601 (0x0080);
+        ISO_EXTENDED_FIXED (ISO_Z_STYLE_FLAG),
+        /**
+         * Fixed width ISO 8601 local time difference (extended format).
+         * For example, "-05:00" and "+05:30".
+         * This style is equivalent to the LDML date format pattern "xxx" and "ZZZZZ".
+         * @draft ICU 51
+         * @provisional This API might change or be removed in a future release.
+         */
+        ISO_EXTENDED_LOCAL_FIXED (ISO_LOCAL_STYLE_FLAG),
+        /**
+         * ISO 8601 local time difference (extended format) with optional seconds field, or the UTC indicator.
+         * For example, "-05:00", "+05:25:38", and "Z"(UTC).
+         * This style is equivalent to the LDML date format pattern "XXXXX".
+         * @draft ICU 51
+         * @provisional This API might change or be removed in a future release.
+         */
+        ISO_EXTENDED_FULL (ISO_Z_STYLE_FLAG),
+        /**
+         * ISO 8601 local time difference (extended format) with optional seconds field.
+         * For example, "-05:00" and "+05:25:38".
+         * This style is equivalent to the LDML date format pattern "xxxxx".
+         * @draft ICU 51
+         * @provisional This API might change or be removed in a future release.
+         */
+        ISO_EXTENDED_LOCAL_FULL (ISO_LOCAL_STYLE_FLAG),
+        /**
+         * Time Zone ID, such as "America/Los_Angeles".
+         * @draft ICU 51
+         * @provisional This API might change or be removed in a future release.
+         */
+        ZONE_ID (0x0200),
+        /**
+         * Short Time Zone ID (BCP 47 Unicode location extension, time zone type value), such as "uslax".
+         * @draft ICU 51
+         * @provisional This API might change or be removed in a future release.
+         */
+        ZONE_ID_SHORT (0x0400),
+        /**
+         * Exemplar location, such as "Los Angeles" and "Paris".
+         * @draft ICU 51
+         * @provisional This API might change or be removed in a future release.
+         */
+        EXEMPLAR_LOCATION (0x0800);
 
         final int flag;
     
@@ -137,29 +243,41 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
      */
     public enum GMTOffsetPatternType {
         /**
-         * Positive offset with hour and minute fields
+         * Positive offset with hours and minutes fields
          * @draft ICU 49
          * @provisional This API might change or be removed in a future release.
          */
-        POSITIVE_HM ("+HH:mm", "Hm", true),
+        POSITIVE_HM ("+H:mm", "Hm", true),
         /**
-         * Positive offset with hour, minute and second fields
+         * Positive offset with hours, minutes and seconds fields
          * @draft ICU 49
          * @provisional This API might change or be removed in a future release.
          */
-        POSITIVE_HMS ("+HH:mm:ss", "Hms", true),
+        POSITIVE_HMS ("+H:mm:ss", "Hms", true),
         /**
-         * Negative offset with hour and minute fields
+         * Negative offset with hours and minutes fields
          * @draft ICU 49
          * @provisional This API might change or be removed in a future release.
          */
-        NEGATIVE_HM ("-HH:mm", "Hm", false),
+        NEGATIVE_HM ("-H:mm", "Hm", false),
         /**
-         * Negative offset with hour, minute and second fields
+         * Negative offset with hours, minutes and seconds fields
          * @draft ICU 49
          * @provisional This API might change or be removed in a future release.
          */
-        NEGATIVE_HMS ("-HH:mm:ss", "Hms", false);
+        NEGATIVE_HMS ("-H:mm:ss", "Hms", false),
+        /**
+         * Positive offset with hours field
+         * @draft ICU 51
+         * @provisional This API might change or be removed in a future release.
+         */
+        POSITIVE_H ("+H", "H", true),
+        /**
+         * Negative offset with hours field
+         * @draft ICU 51
+         * @provisional This API might change or be removed in a future release.
+         */
+        NEGATIVE_H ("-H", "H", false);
 
         private String _defaultPattern;
         private String _required;
@@ -247,6 +365,8 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
     private transient String _gmtPatternPrefix;
     private transient String _gmtPatternSuffix;
     private transient Object[][] _gmtOffsetPatternItems;
+    // cache if offset hours and minutes are abutting
+    private transient boolean _abuttingOffsetHoursAndMinutes;
 
     private transient String _region;
 
@@ -267,11 +387,16 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
     private static final String ASCII_DIGITS = "0123456789";
     private static final String ISO8601_UTC = "Z";
 
+    private static final String UNKNOWN_ZONE_ID = "Etc/Unknown";
+    private static final String UNKNOWN_SHORT_ZONE_ID = "unk";
+    private static final String UNKNOWN_LOCATION = "Unknown";
+
     // Order of GMT offset pattern parsing, *_HMS must be evaluated first
     // because *_HM is most likely a substring of *_HMS 
     private static final GMTOffsetPatternType[] PARSE_GMT_OFFSET_TYPES = {
         GMTOffsetPatternType.POSITIVE_HMS, GMTOffsetPatternType.NEGATIVE_HMS,
         GMTOffsetPatternType.POSITIVE_HM, GMTOffsetPatternType.NEGATIVE_HM,
+        GMTOffsetPatternType.POSITIVE_H, GMTOffsetPatternType.NEGATIVE_H,
     };
 
     private static final int MILLIS_PER_HOUR = 60 * 60 * 1000;
@@ -290,10 +415,11 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
 
     private static TimeZoneFormatCache _tzfCache = new TimeZoneFormatCache();
 
-    // The filter used for searching all specific names
-    private static final EnumSet<NameType> ALL_SPECIFIC_NAME_TYPES = EnumSet.of(
+    // The filter used for searching all specific names and exemplar location names
+    private static final EnumSet<NameType> ALL_SIMPLE_NAME_TYPES = EnumSet.of(
         NameType.LONG_STANDARD, NameType.LONG_DAYLIGHT,
-        NameType.SHORT_STANDARD, NameType.SHORT_DAYLIGHT
+        NameType.SHORT_STANDARD, NameType.SHORT_DAYLIGHT,
+        NameType.EXEMPLAR_LOCATION
     );
 
     // The filter used for searching all generic names
@@ -301,6 +427,9 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
         GenericNameType.LOCATION, GenericNameType.LONG, GenericNameType.SHORT
     );
 
+    private static volatile TextTrieMap<String> ZONE_ID_TRIE;
+    private static volatile TextTrieMap<String> SHORT_ZONE_ID_TRIE;
+
     /**
      * The protected constructor for subclassing.
      * @param locale the locale
@@ -346,8 +475,10 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
         String[] gmtOffsetPatterns = new String[GMTOffsetPatternType.values().length];
         if (hourFormats != null) {
             String[] hourPatterns = hourFormats.split(";", 2);
+            gmtOffsetPatterns[GMTOffsetPatternType.POSITIVE_H.ordinal()] = truncateOffsetPattern(hourPatterns[0]);
             gmtOffsetPatterns[GMTOffsetPatternType.POSITIVE_HM.ordinal()] = hourPatterns[0];
             gmtOffsetPatterns[GMTOffsetPatternType.POSITIVE_HMS.ordinal()] = expandOffsetPattern(hourPatterns[0]);
+            gmtOffsetPatterns[GMTOffsetPatternType.NEGATIVE_H.ordinal()] = truncateOffsetPattern(hourPatterns[1]);
             gmtOffsetPatterns[GMTOffsetPatternType.NEGATIVE_HM.ordinal()] = hourPatterns[1];
             gmtOffsetPatterns[GMTOffsetPatternType.NEGATIVE_HMS.ordinal()] = expandOffsetPattern(hourPatterns[1]);
         } else {
@@ -503,6 +634,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
 
         _gmtOffsetPatterns[type.ordinal()] = pattern;
         _gmtOffsetPatternItems[type.ordinal()] = parsedItems;
+        checkAbuttingHoursAndMinutes();
 
         return this;
     }
@@ -619,42 +751,43 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
     }
 
     /**
-     * Returns the RFC822 style time zone string for the given offset.
-     * For example, "-0800".
+     * Returns the ISO 8601 basic time zone string for the given offset.
+     * For example, "-08", "-0830" and "Z"
      * 
      * @param offset the offset from GMT(UTC) in milliseconds.
-     * @return the RFC822 style GMT(UTC) offset format.
-     * @see #parseOffsetRFC822(String, ParsePosition)
+     * @param useUtcIndicator true if ISO 8601 UTC indicator "Z" is used when the offset is 0.
+     * @param isShort true if shortest form is used.
+     * @param ignoreSeconds true if non-zero offset seconds is appended.
+     * @return the ISO 8601 basic format.
      * @throws IllegalArgumentException if the specified offset is out of supported range
      * (-24 hours &lt; offset &lt; +24 hours).
-     * @draft ICU 49
+     * @see #formatOffsetISO8601Extended(int, boolean, boolean, boolean)
+     * @see #parseOffsetISO8601(String, ParsePosition)
+     * @draft ICU 51
      * @provisional This API might change or be removed in a future release.
      */
-    public final String formatOffsetRFC822(int offset) {
-        // Note: OffsetFields.HMS as maxFields is an ICU extension. RFC822 specification
-        // defines exactly 4 digits for the offset field in HHss format.
-        return formatOffsetWithAsciiDigits(offset, null, OffsetFields.HM, OffsetFields.HMS);
+    public final String formatOffsetISO8601Basic(int offset, boolean useUtcIndicator, boolean isShort, boolean ignoreSeconds) {
+        return formatOffsetISO8601(offset, true, useUtcIndicator, isShort, ignoreSeconds);
     }
 
     /**
-     * Returns the ISO 8601 style (extended format) time zone string for the given offset.
-     * For example, "-08:00" and "Z"
+     * Returns the ISO 8601 extended time zone string for the given offset.
+     * For example, "-08:00", "-08:30" and "Z"
      * 
      * @param offset the offset from GMT(UTC) in milliseconds.
-     * @return the ISO 8601 style GMT(UTC) offset format.
-     * @see #parseOffsetISO8601(String, ParsePosition)
+     * @param useUtcIndicator true if ISO 8601 UTC indicator "Z" is used when the offset is 0.
+     * @param isShort true if shortest form is used.
+     * @param ignoreSeconds true if non-zero offset seconds is appended.
+     * @return the ISO 8601 extended format.
      * @throws IllegalArgumentException if the specified offset is out of supported range
      * (-24 hours &lt; offset &lt; +24 hours).
-     * @draft ICU 49
+     * @see #formatOffsetISO8601Basic(int, boolean, boolean, boolean)
+     * @see #parseOffsetISO8601(String, ParsePosition)
+     * @draft ICU 51
      * @provisional This API might change or be removed in a future release.
      */
-    public final String formatOffsetISO8601(int offset) {
-        if (offset == 0) {
-            return ISO8601_UTC;
-        }
-        // Note: OffsetFields.HMS as maxFields is an ICU extension. ISO 8601 specification does
-        // not support second field.
-        return formatOffsetWithAsciiDigits(offset, ':', OffsetFields.HM, OffsetFields.HMS);
+    public final String formatOffsetISO8601Extended(int offset, boolean useUtcIndicator, boolean isShort, boolean ignoreSeconds) {
+        return formatOffsetISO8601(offset, false, useUtcIndicator, isShort, ignoreSeconds);
     }
 
     /**
@@ -666,6 +799,9 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
      * <li>Offset digits (e.g. "0123456789" - see {@link #getGMTOffsetDigits()})
      * <li>GMT zero format (e.g. "GMT" - see {@link #getGMTZeroFormat()})
      * </ul>
+     * This format always uses 2 digit hours and minutes. When the given offset has non-zero
+     * seconds, 2 digit seconds field will be appended. For example,
+     * GMT+05:00 and GMT+05:28:06.
      * @param offset the offset from GMT(UTC) in milliseconds.
      * @return the localized GMT format string
      * @see #parseOffsetLocalizedGMT(String, ParsePosition)
@@ -675,63 +811,31 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
      * @provisional This API might change or be removed in a future release.
      */
     public String formatOffsetLocalizedGMT(int offset) {
-        if (offset == 0) {
-            return _gmtZeroFormat;
-        }
-
-        StringBuilder buf = new StringBuilder();
-        boolean positive = true;
-        if (offset < 0) {
-            offset = -offset;
-            positive = false;
-        }
-
-        int offsetH = offset / MILLIS_PER_HOUR;
-        offset = offset % MILLIS_PER_HOUR;
-        int offsetM = offset / MILLIS_PER_MINUTE;
-        offset = offset % MILLIS_PER_MINUTE;
-        int offsetS = offset / MILLIS_PER_SECOND;
-
-        if (offsetH > MAX_OFFSET_HOUR || offsetM > MAX_OFFSET_MINUTE || offsetS > MAX_OFFSET_SECOND) {
-            throw new IllegalArgumentException("Offset out of range :" + offset);
-        }
-
-        Object[] offsetPatternItems;
-        if (positive) {
-            offsetPatternItems = (offsetS == 0) ?
-                    _gmtOffsetPatternItems[GMTOffsetPatternType.POSITIVE_HM.ordinal()] :
-                    _gmtOffsetPatternItems[GMTOffsetPatternType.POSITIVE_HMS.ordinal()];
-        } else {
-            offsetPatternItems = (offsetS == 0) ?
-                    _gmtOffsetPatternItems[GMTOffsetPatternType.NEGATIVE_HM.ordinal()] :
-                    _gmtOffsetPatternItems[GMTOffsetPatternType.NEGATIVE_HMS.ordinal()];
-        }
-
-        // Building the GMT format string
-        buf.append(_gmtPatternPrefix);
+        return formatOffsetLocalizedGMT(offset, false);
+    }
 
-        for (Object item : offsetPatternItems) {
-            if (item instanceof String) {
-                // pattern literal
-                buf.append((String)item);
-            } else if (item instanceof GMTOffsetField) {
-                // Hour/minute/second field
-                GMTOffsetField field = (GMTOffsetField)item;
-                switch (field.getType()) {
-                case 'H':
-                    appendOffsetDigits(buf, offsetH, field.getWidth());
-                    break;
-                case 'm':
-                    appendOffsetDigits(buf, offsetM, field.getWidth());
-                    break;
-                case 's':
-                    appendOffsetDigits(buf, offsetS, field.getWidth());
-                    break;
-                }
-            }
-        }
-        buf.append(_gmtPatternSuffix);
-        return buf.toString();
+    /**
+     * Returns the short localized GMT(UTC) offset format for the given offset.
+     * The short localized GMT offset is defined by;
+     * <ul>
+     * <li>GMT format pattern (e.g. "GMT {0}" - see {@link #getGMTPattern()})
+     * <li>Offset time pattern (e.g. "+HH:mm" - see {@link #getGMTOffsetPattern(GMTOffsetPatternType)})
+     * <li>Offset digits (e.g. "0123456789" - see {@link #getGMTOffsetDigits()})
+     * <li>GMT zero format (e.g. "GMT" - see {@link #getGMTZeroFormat()})
+     * </ul>
+     * This format uses the shortest representation of offset. The hours field does not
+     * have leading zero and lower fields with zero will be truncated. For example,
+     * GMT+5 and GMT+530.
+     * @param offset the offset from GMT(UTC) in milliseconds.
+     * @return the short localized GMT format string
+     * @see #parseOffsetLocalizedGMT(String, ParsePosition)
+     * @throws IllegalArgumentException if the specified offset is out of supported range
+     * (-24 hours &lt; offset &lt; +24 hours).
+     * @draft ICU 51
+     * @provisional This API might change or be removed in a future release.
+     */
+    public String formatOffsetShortLocalizedGMT(int offset) {
+        return formatOffsetLocalizedGMT(offset, true);
     }
 
     /**
@@ -800,9 +904,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
         case SPECIFIC_SHORT:
             result = formatSpecific(tz, NameType.SHORT_STANDARD, NameType.SHORT_DAYLIGHT, date, timeType);
             break;
-        case RFC822:
-        case ISO8601:
-        case LOCALIZED_GMT:
+        default:
             // will be handled below
             break;
         }
@@ -810,15 +912,75 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
         if (result == null) {
             int[] offsets = {0, 0};
             tz.getOffset(date, false, offsets);
+            int offset = offsets[0] + offsets[1];
+
             switch (style) {
-            case RFC822:
-                result = formatOffsetRFC822(offsets[0] + offsets[1]);
+            case GENERIC_LOCATION:
+            case GENERIC_LONG:
+            case SPECIFIC_LONG:
+            case LOCALIZED_GMT:
+                result = formatOffsetLocalizedGMT(offset);
+                break;
+
+            case GENERIC_SHORT:
+            case SPECIFIC_SHORT:
+            case LOCALIZED_GMT_SHORT:
+                result = formatOffsetShortLocalizedGMT(offset);
+                break;
+
+            case ISO_BASIC_SHORT:
+                result = formatOffsetISO8601Basic(offset, true, true, true);
+                break;
+
+            case ISO_BASIC_LOCAL_SHORT:
+                result = formatOffsetISO8601Basic(offset, false, true, true);
+                break;
+
+            case ISO_BASIC_FIXED:
+                result = formatOffsetISO8601Basic(offset, true, false, true);
+                break;
+
+            case ISO_BASIC_LOCAL_FIXED:
+                result = formatOffsetISO8601Basic(offset, false, false, true);
+                break;
+
+            case ISO_BASIC_FULL:
+                result = formatOffsetISO8601Basic(offset, true, false, false);
+                break;
+
+            case ISO_BASIC_LOCAL_FULL:
+                result = formatOffsetISO8601Basic(offset, false, false, false);
+                break;
+
+            case ISO_EXTENDED_FIXED:
+                result = formatOffsetISO8601Extended(offset, true, false, true);
+                break;
+
+            case ISO_EXTENDED_LOCAL_FIXED:
+                result = formatOffsetISO8601Extended(offset, false, false, true);
+                break;
+
+            case ISO_EXTENDED_FULL:
+                result = formatOffsetISO8601Extended(offset, true, false, false);
+                break;
+
+            case ISO_EXTENDED_LOCAL_FULL:
+                result = formatOffsetISO8601Extended(offset, false, false, false);
+                break;
+
+            case ZONE_ID:
+                result = tz.getID();
                 break;
-            case ISO8601:
-                result = formatOffsetISO8601(offsets[0] + offsets[1]);
+
+            case ZONE_ID_SHORT:
+                result = ZoneMeta.getShortID(tz);
+                if (result == null) {
+                    result = UNKNOWN_SHORT_ZONE_ID;
+                }
                 break;
-            default: // Other than RFC822/ISO8601, including fallback from SPECIFIC_XXX/GENERIC_XXX
-                result = formatOffsetLocalizedGMT(offsets[0] + offsets[1]);
+
+            case EXEMPLAR_LOCATION:
+                result = formatExemplarLocation(tz);
                 break;
             }
             // time type
@@ -833,64 +995,18 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
     }
 
     /**
-     * Returns offset from GMT(UTC) in milliseconds for the given RFC822
-     * style time zone string. When the given string is not an RFC822 time zone
-     * string, this method sets the current position as the error index
-     * to <code>ParsePosition pos</code> and returns 0.
-     * 
-     * @param text the text contains RFC822 style time zone string (e.g. "-0800")
-     * at the position.
-     * @param pos the position.
-     * @return the offset from GMT(UTC) in milliseconds for the given RFC822 style
-     * time zone string.
-     * @see #formatOffsetRFC822(int)
-     * @draft ICU 49
-     * @provisional This API might change or be removed in a future release.
-     */
-    public final int parseOffsetRFC822(String text, ParsePosition pos) {
-        int start = pos.getIndex();
-        if (start >= text.length()) {
-            pos.setErrorIndex(start);
-            return 0;
-        }
-
-        int sign;
-        char signChar = text.charAt(start);
-        if (signChar == '+') {
-            sign = 1;
-        } else if (signChar == '-') {
-            sign = -1;
-        } else {
-            // Not an RFC822 offset string
-            pos.setErrorIndex(start);
-            return 0;
-        }
-
-        // Parse digits
-        pos.setIndex(start + 1);
-        int offset = parseAbuttingAsciiOffsetFields(text, pos, OffsetFields.H, OffsetFields.HMS, false);
-
-        if (pos.getErrorIndex() != -1) {
-            pos.setIndex(start);    // reset
-            pos.setErrorIndex(start);
-            return 0;
-        }
-
-        return sign * offset;
-    }
-
-    /**
-     * Returns offset from GMT(UTC) in milliseconds for the given ISO 8601 style
-     * (extended format) time zone string. When the given string is not an ISO 8601 time
+     * Returns offset from GMT(UTC) in milliseconds for the given ISO 8601
+     * basic or extended time zone string. When the given string is not an ISO 8601 time
      * zone string, this method sets the current position as the error index
      * to <code>ParsePosition pos</code> and returns 0.
      * 
-     * @param text the text contains ISO 8601 style time zone string (e.g. "-08:00", "Z")
+     * @param text the text contains ISO 8601 style time zone string (e.g. "-08", "-0800", "-08:00", and "Z")
      * at the position.
      * @param pos the position.
      * @return the offset from GMT(UTC) in milliseconds for the given ISO 8601 style
      * time zone string.
-     * @see #formatOffsetISO8601(int)
+     * @see #formatOffsetISO8601Basic(int, boolean, boolean, boolean)
+     * @see #formatOffsetISO8601Extended(int, boolean, boolean, boolean)
      * @draft ICU 49
      * @provisional This API might change or be removed in a future release.
      */
@@ -913,7 +1029,25 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
      * @provisional This API might change or be removed in a future release.
      */
     public int parseOffsetLocalizedGMT(String text, ParsePosition pos) {
-        return parseOffsetLocalizedGMT(text, pos, null);
+        return parseOffsetLocalizedGMT(text, pos, false, null);
+    }
+
+    /**
+     * Returns offset from GMT(UTC) in milliseconds for the given short localized GMT
+     * offset format string. When the given string cannot be parsed, this method
+     * sets the current position as the error index to <code>ParsePosition pos</code>
+     * and returns 0.
+     * 
+     * @param text the text contains a short localized GMT offset string at the position.
+     * @param pos the position.
+     * @return the offset from GMT(UTC) in milliseconds for the given short localized GMT
+     * offset format string.
+     * @see #formatOffsetShortLocalizedGMT(int)
+     * @draft ICU 51
+     * @provisional This API might change or be removed in a future release.
+     */
+    public int parseOffsetShortLocalizedGMT(String text, ParsePosition pos) {
+        return parseOffsetLocalizedGMT(text, pos, true, null);
     }
 
     /**
@@ -943,12 +1077,11 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
         int maxPos = text.length();
         int offset;
 
-        boolean fallbackLocalizedGMT = false;
-        if (style == Style.SPECIFIC_LONG || style == Style.SPECIFIC_SHORT
-                || style == Style.GENERIC_LONG || style == Style.GENERIC_SHORT || style == Style.GENERIC_LOCATION) {
-            // above styles may use localized gmt format as fallback
-            fallbackLocalizedGMT = true;
-        }
+        // Styles using localized GMT format as fallback
+        boolean fallbackLocalizedGMT =
+                (style == Style.SPECIFIC_LONG || style == Style.GENERIC_LONG || style == Style.GENERIC_LOCATION);
+        boolean fallbackShortLocalizedGMT =
+                (style == Style.SPECIFIC_SHORT || style == Style.GENERIC_SHORT);
 
         int evaluated = 0;  // bit flags representing already evaluated styles
         ParsePosition tmpPos = new ParsePosition(startIdx);
@@ -957,9 +1090,9 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
         int parsedPos = -1;                 // stores successfully parsed offset position for later use
 
         // Try localized GMT format first if necessary
-        if (fallbackLocalizedGMT) {
+        if (fallbackLocalizedGMT || fallbackShortLocalizedGMT) {
             Output<Boolean> hasDigitOffset = new Output<Boolean>(false);
-            offset = parseOffsetLocalizedGMT(text, tmpPos, hasDigitOffset);
+            offset = parseOffsetLocalizedGMT(text, tmpPos, fallbackShortLocalizedGMT, hasDigitOffset);
             if (tmpPos.getErrorIndex() == -1) {
                 // Even when the input text was successfully parsed as a localized GMT format text,
                 // we may still need to evaluate the specified style if -
@@ -972,51 +1105,88 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
                 parsedOffset = offset;
                 parsedPos = tmpPos.getIndex();
             }
-            evaluated |= Style.LOCALIZED_GMT.flag;
-
-            tmpPos.setIndex(startIdx);
-            tmpPos.setErrorIndex(-1);
+            // Note: For now, no distinction between long/short localized GMT format in the parser.
+            // This might be changed in future.
+//            evaluated |= (fallbackLocalizedGMT ? Style.LOCALIZED_GMT.flag : Style.LOCALIZED_GMT_SHORT.flag);
+            evaluated |= (Style.LOCALIZED_GMT.flag | Style.LOCALIZED_GMT_SHORT.flag);
         }
 
         // Try the specified style
         switch (style) {
-            case RFC822:
+            case LOCALIZED_GMT:
             {
-                offset = parseOffsetRFC822(text, tmpPos);
+                tmpPos.setIndex(startIdx);
+                tmpPos.setErrorIndex(-1);
+
+                offset = parseOffsetLocalizedGMT(text, tmpPos);
                 if (tmpPos.getErrorIndex() == -1) {
                     pos.setIndex(tmpPos.getIndex());
                     return getTimeZoneForOffset(offset);
                 }
+                // Note: For now, no distinction between long/short localized GMT format in the parser.
+                // This might be changed in future.
+                evaluated |= Style.LOCALIZED_GMT_SHORT.flag;
                 break;
             }
-            case LOCALIZED_GMT:
+            case LOCALIZED_GMT_SHORT:
             {
-                offset = parseOffsetLocalizedGMT(text, tmpPos);
+                tmpPos.setIndex(startIdx);
+                tmpPos.setErrorIndex(-1);
+
+                offset = parseOffsetShortLocalizedGMT(text, tmpPos);
                 if (tmpPos.getErrorIndex() == -1) {
                     pos.setIndex(tmpPos.getIndex());
                     return getTimeZoneForOffset(offset);
                 }
+                // Note: For now, no distinction between long/short localized GMT format in the parser.
+                // This might be changed in future.
+                evaluated |= Style.LOCALIZED_GMT.flag;
                 break;
             }
-            case ISO8601:
+
+            case ISO_BASIC_SHORT:
+            case ISO_BASIC_FIXED:
+            case ISO_BASIC_FULL:
+            case ISO_EXTENDED_FIXED:
+            case ISO_EXTENDED_FULL:
             {
+                tmpPos.setIndex(startIdx);
+                tmpPos.setErrorIndex(-1);
+
                 offset = parseOffsetISO8601(text, tmpPos);
                 if (tmpPos.getErrorIndex() == -1) {
                     pos.setIndex(tmpPos.getIndex());
                     return getTimeZoneForOffset(offset);
                 }
-                // Note: ISO 8601 parser also support basic format (without ':'),
-                // which is same with RFC 822 format.
-                evaluated |= Style.RFC822.flag;
                 break;
             }
+
+            case ISO_BASIC_LOCAL_SHORT:
+            case ISO_BASIC_LOCAL_FIXED:
+            case ISO_BASIC_LOCAL_FULL:
+            case ISO_EXTENDED_LOCAL_FIXED:
+            case ISO_EXTENDED_LOCAL_FULL:
+            {
+                tmpPos.setIndex(startIdx);
+                tmpPos.setErrorIndex(-1);
+
+                // Exclude the case of UTC Indicator "Z" here
+                Output<Boolean> hasDigitOffset = new Output<Boolean>(false);
+                offset = parseOffsetISO8601(text, tmpPos, false, hasDigitOffset);
+                if (tmpPos.getErrorIndex() == -1 && hasDigitOffset.value) {
+                    pos.setIndex(tmpPos.getIndex());
+                    return getTimeZoneForOffset(offset);
+                }
+                break;
+            }
+
             case SPECIFIC_LONG:
             case SPECIFIC_SHORT:
             {
                 // Specific styles
                 EnumSet<NameType> nameTypes = null;
                 if (style == Style.SPECIFIC_LONG) {
-                    nameTypes = EnumSet.of(NameType.LONG_STANDARD, NameType.LONG_DAYLIGHT);                    
+                    nameTypes = EnumSet.of(NameType.LONG_STANDARD, NameType.LONG_DAYLIGHT);
                 } else {
                     assert style == Style.SPECIFIC_SHORT;
                     nameTypes = EnumSet.of(NameType.SHORT_STANDARD, NameType.SHORT_DAYLIGHT);
@@ -1062,6 +1232,42 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
                 }
                 break;
             }
+            case ZONE_ID:
+            {
+                tmpPos.setIndex(startIdx);
+                tmpPos.setErrorIndex(-1);
+
+                String id = parseZoneID(text, tmpPos);
+                if (tmpPos.getErrorIndex() == -1) {
+                    pos.setIndex(tmpPos.getIndex());
+                    return TimeZone.getTimeZone(id);
+                }
+                break;
+            }
+            case ZONE_ID_SHORT:
+            {
+                tmpPos.setIndex(startIdx);
+                tmpPos.setErrorIndex(-1);
+
+                String id = parseShortZoneID(text, tmpPos);
+                if (tmpPos.getErrorIndex() == -1) {
+                    pos.setIndex(tmpPos.getIndex());
+                    return TimeZone.getTimeZone(id);
+                }
+                break;
+            }
+            case EXEMPLAR_LOCATION:
+            {
+                tmpPos.setIndex(startIdx);
+                tmpPos.setErrorIndex(-1);
+
+                String id = parseExemplarLocation(text, tmpPos);
+                if (tmpPos.getErrorIndex() == -1) {
+                    pos.setIndex(tmpPos.getIndex());
+                    return TimeZone.getTimeZone(id);
+                }
+                break;
+            }
         }
         evaluated |= style.flag;
 
@@ -1080,13 +1286,17 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
 
         // Failed to parse the input text as the time zone format in the specified style.
         // Check the longest match among other styles below.
+        String parsedID = null;                     // stores successfully parsed zone ID for later use
+        TimeType parsedTimeType = TimeType.UNKNOWN; // stores successfully parsed time type for later use
         assert parsedPos < 0;
         assert parsedOffset == UNKNOWN_OFFSET;
-        tmpPos.setIndex(startIdx);
-        tmpPos.setErrorIndex(-1);
 
         // ISO 8601
-        if ((evaluated & Style.ISO8601.flag) == 0) {
+        if (parsedPos < maxPos &&
+                ((evaluated & ISO_Z_STYLE_FLAG) == 0 || (evaluated & ISO_LOCAL_STYLE_FLAG) == 0)) {
+            tmpPos.setIndex(startIdx);
+            tmpPos.setErrorIndex(-1);
+
             Output<Boolean> hasDigitOffset = new Output<Boolean>(false);
             offset = parseOffsetISO8601(text, tmpPos, false, hasDigitOffset);
             if (tmpPos.getErrorIndex() == -1) {
@@ -1095,48 +1305,65 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
                     return getTimeZoneForOffset(offset);
                 }
                 // Note: When ISO 8601 format contains offset digits, it should not
-                // collide with other formats (except RFC 822, which is compatible with
-                // ISO 8601 basic format). However, ISO 8601 UTC format "Z" (single letter)
-                // may collide with other names. In this case, we need to evaluate other
-                // names.
-                parsedOffset = offset;
-                parsedPos = tmpPos.getIndex();
-                assert parsedPos == startIdx + 1;   // only when "Z" is used
+                // collide with other formats. However, ISO 8601 UTC format "Z" (single letter)
+                // may collide with other names. In this case, we need to evaluate other names.
+                if (parsedPos < tmpPos.getIndex()) {
+                    parsedOffset = offset;
+                    parsedID = null;
+                    parsedTimeType = TimeType.UNKNOWN;
+                    parsedPos = tmpPos.getIndex();
+                    assert parsedPos == startIdx + 1;   // only when "Z" is used
+                }
             }
+        }
+
+
+        // Localized GMT format
+        if (parsedPos < maxPos &&
+                (evaluated & Style.LOCALIZED_GMT.flag) == 0) {
             tmpPos.setIndex(startIdx);
             tmpPos.setErrorIndex(-1);
+
+            Output<Boolean> hasDigitOffset = new Output<Boolean>(false);
+            offset = parseOffsetLocalizedGMT(text, tmpPos, false, hasDigitOffset);
+            if (tmpPos.getErrorIndex() == -1) {
+                if (tmpPos.getIndex() == maxPos || hasDigitOffset.value) {
+                    pos.setIndex(tmpPos.getIndex());
+                    return getTimeZoneForOffset(offset);
+                }
+                // Evaluate other names - see the comment earlier in this method.
+                if (parsedPos < tmpPos.getIndex()) {
+                    parsedOffset = offset;
+                    parsedID = null;
+                    parsedTimeType = TimeType.UNKNOWN;
+                    parsedPos = tmpPos.getIndex();
+                }
+            }
         }
 
-        // RFC 822
-        // Note: ISO 8601 parser supports RFC 822 format. So we do not need to parse
-        // it as RFC 822 here. This might be changed in future when we support
-        // strict format option for ISO 8601 or RFC 822. 
-//        if ((evaluated & Style.RFC822.flag) == 0) {
-//            offset = parseOffsetRFC822(text, tmpPos);
-//            if (tmpPos.getErrorIndex() == -1) {
-//                pos.setIndex(tmpPos.getIndex());
-//                return getTimeZoneForOffset(offset);
-//            }
-//            tmpPos.setIndex(startIdx);
-//            tmpPos.setErrorIndex(-1);
-//        }
+        if (parsedPos < maxPos &&
+                (evaluated & Style.LOCALIZED_GMT_SHORT.flag) == 0) {
+            tmpPos.setIndex(startIdx);
+            tmpPos.setErrorIndex(-1);
 
-        // Localized GMT format
-        if ((evaluated & Style.LOCALIZED_GMT.flag) == 0) {
             Output<Boolean> hasDigitOffset = new Output<Boolean>(false);
-            offset = parseOffsetLocalizedGMT(text, tmpPos, hasDigitOffset);
+            offset = parseOffsetLocalizedGMT(text, tmpPos, true, hasDigitOffset);
             if (tmpPos.getErrorIndex() == -1) {
                 if (tmpPos.getIndex() == maxPos || hasDigitOffset.value) {
                     pos.setIndex(tmpPos.getIndex());
                     return getTimeZoneForOffset(offset);
                 }
                 // Evaluate other names - see the comment earlier in this method.
-                parsedOffset = offset;
-                parsedPos = tmpPos.getIndex();
+                if (parsedPos < tmpPos.getIndex()) {
+                    parsedOffset = offset;
+                    parsedID = null;
+                    parsedTimeType = TimeType.UNKNOWN;
+                    parsedPos = tmpPos.getIndex();
+                }
             }
         }
 
-        // When ParseOption.ALL_STYLES is available, we also try to look all possible display names.
+        // When ParseOption.ALL_STYLES is available, we also try to look all possible display names and IDs.
         // For example, when style is GENERIC_LONG, "EST" (SPECIFIC_SHORT) is never
         // used for America/New_York. With parseAllStyles true, this code parses "EST"
         // as America/New_York.
@@ -1150,43 +1377,78 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
                 : options.contains(ParseOption.ALL_STYLES);
 
         if (parseAllStyles) {
-            // Try all specific names first
-            Collection<MatchInfo> specificMatches = _tznames.find(text, startIdx, ALL_SPECIFIC_NAME_TYPES);
-            MatchInfo specificMatch = null;
-            if (specificMatches != null) {
-                for (MatchInfo match : specificMatches) {
-                    if (startIdx + match.matchLength() > parsedPos) {
-                        specificMatch = match;
-                        parsedPos = startIdx + match.matchLength();
+            // Try all specific names and exemplar location names
+            if (parsedPos < maxPos) {
+                Collection<MatchInfo> specificMatches = _tznames.find(text, startIdx, ALL_SIMPLE_NAME_TYPES);
+                MatchInfo specificMatch = null;
+                int matchPos = -1;
+                if (specificMatches != null) {
+                    for (MatchInfo match : specificMatches) {
+                        if (startIdx + match.matchLength() > matchPos) {
+                            specificMatch = match;
+                            matchPos = startIdx + match.matchLength();
+                        }
                     }
                 }
+                if (parsedPos < matchPos) {
+                    parsedPos = matchPos;
+                    parsedID = getTimeZoneID(specificMatch.tzID(), specificMatch.mzID());
+                    parsedTimeType = getTimeType(specificMatch.nameType());
+                    parsedOffset = UNKNOWN_OFFSET;
+                }
+                
             }
-
-            GenericMatchInfo genericMatch = null;
+            // Try generic names
             if (parsedPos < maxPos) {
-                // Try generic names
-                genericMatch = getTimeZoneGenericNames().findBestMatch(text, startIdx, ALL_GENERIC_NAME_TYPES);
+                GenericMatchInfo genericMatch = getTimeZoneGenericNames().findBestMatch(text, startIdx, ALL_GENERIC_NAME_TYPES);
+                if (genericMatch != null && parsedPos < startIdx + genericMatch.matchLength()) {
+                    parsedPos = startIdx + genericMatch.matchLength();
+                    parsedID = genericMatch.tzID();
+                    parsedTimeType = genericMatch.timeType();
+                    parsedOffset = UNKNOWN_OFFSET;
+                }
             }
 
-            // Pick up better match
-            if (genericMatch != null && (startIdx + genericMatch.matchLength() > parsedPos)) {
-                // use this one
-                parsedPos = startIdx + genericMatch.matchLength();
-                timeType.value = genericMatch.timeType();
-                pos.setIndex(parsedPos);
-                return TimeZone.getTimeZone(genericMatch.tzID());
-            } else if (specificMatch != null){
-                timeType.value = getTimeType(specificMatch.nameType());
-                pos.setIndex(parsedPos);
-                return TimeZone.getTimeZone(getTimeZoneID(specificMatch.tzID(), specificMatch.mzID()));
+            // Try time zone ID
+            if (parsedPos < maxPos && (evaluated & Style.ZONE_ID.flag) == 0) {
+                tmpPos.setIndex(startIdx);
+                tmpPos.setErrorIndex(-1);
+
+                String id = parseZoneID(text, tmpPos);
+                if (tmpPos.getErrorIndex() == -1 && parsedPos < tmpPos.getIndex()) {
+                    parsedPos = tmpPos.getIndex();
+                    parsedID = id;
+                    parsedTimeType = TimeType.UNKNOWN;
+                    parsedOffset = UNKNOWN_OFFSET;
+                }
+            }
+            // Try short time zone ID
+            if (parsedPos < maxPos && (evaluated & Style.ZONE_ID_SHORT.flag) == 0) {
+                tmpPos.setIndex(startIdx);
+                tmpPos.setErrorIndex(-1);
+
+                String id = parseShortZoneID(text, tmpPos);
+                if (tmpPos.getErrorIndex() == -1 && parsedPos < tmpPos.getIndex()) {
+                    parsedPos = tmpPos.getIndex();
+                    parsedID = id;
+                    parsedTimeType = TimeType.UNKNOWN;
+                    parsedOffset = UNKNOWN_OFFSET;
+                }
             }
         }
 
         if (parsedPos > startIdx) {
-            // Parsed successfully as one of 'offset' format
-            assert parsedOffset != UNKNOWN_OFFSET;
+            // Parsed successfully
+            TimeZone parsedTZ = null;
+            if (parsedID != null) {
+                parsedTZ = TimeZone.getTimeZone(parsedID);
+            } else {
+                assert parsedOffset != UNKNOWN_OFFSET;
+                parsedTZ = getTimeZoneForOffset(parsedOffset);
+            }
+            timeType.value = parsedTimeType;
             pos.setIndex(parsedPos);
-            return getTimeZoneForOffset(parsedOffset);
+            return parsedTZ;
         }
 
         pos.setErrorIndex(startIdx);
@@ -1318,6 +1580,146 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
         return parse(source, pos);
     }
 
+    /**
+     * Private method used for localized GMT formatting.
+     * @param offset the zone's UTC offset
+     * @param isShort true if the short localized GMT format is desired
+     * @return the localized GMT string
+     */
+    private String formatOffsetLocalizedGMT(int offset, boolean isShort) {
+        if (offset == 0) {
+            return _gmtZeroFormat;
+        }
+
+        StringBuilder buf = new StringBuilder();
+        boolean positive = true;
+        if (offset < 0) {
+            offset = -offset;
+            positive = false;
+        }
+
+        int offsetH = offset / MILLIS_PER_HOUR;
+        offset = offset % MILLIS_PER_HOUR;
+        int offsetM = offset / MILLIS_PER_MINUTE;
+        offset = offset % MILLIS_PER_MINUTE;
+        int offsetS = offset / MILLIS_PER_SECOND;
+
+        if (offsetH > MAX_OFFSET_HOUR || offsetM > MAX_OFFSET_MINUTE || offsetS > MAX_OFFSET_SECOND) {
+            throw new IllegalArgumentException("Offset out of range :" + offset);
+        }
+
+        Object[] offsetPatternItems;
+        if (positive) {
+            if (offsetS != 0) {
+                offsetPatternItems = _gmtOffsetPatternItems[GMTOffsetPatternType.POSITIVE_HMS.ordinal()];
+            } else if (offsetM != 0 || !isShort) {
+                offsetPatternItems = _gmtOffsetPatternItems[GMTOffsetPatternType.POSITIVE_HM.ordinal()];
+            } else {
+                offsetPatternItems = _gmtOffsetPatternItems[GMTOffsetPatternType.POSITIVE_H.ordinal()];
+            }
+        } else {
+            if (offsetS != 0) {
+                offsetPatternItems = _gmtOffsetPatternItems[GMTOffsetPatternType.NEGATIVE_HMS.ordinal()];
+            } else if (offsetM != 0 || !isShort) {
+                offsetPatternItems = _gmtOffsetPatternItems[GMTOffsetPatternType.NEGATIVE_HM.ordinal()];
+            } else {
+                offsetPatternItems = _gmtOffsetPatternItems[GMTOffsetPatternType.NEGATIVE_H.ordinal()];
+            }
+        }
+
+        // Building the GMT format string
+        buf.append(_gmtPatternPrefix);
+
+        for (Object item : offsetPatternItems) {
+            if (item instanceof String) {
+                // pattern literal
+                buf.append((String)item);
+            } else if (item instanceof GMTOffsetField) {
+                // Hour/minute/second field
+                GMTOffsetField field = (GMTOffsetField)item;
+                switch (field.getType()) {
+                case 'H':
+                    appendOffsetDigits(buf, offsetH, (isShort ? 1 : 2));
+                    break;
+                case 'm':
+                    appendOffsetDigits(buf, offsetM, 2);
+                    break;
+                case 's':
+                    appendOffsetDigits(buf, offsetS, 2);
+                    break;
+                }
+            }
+        }
+        buf.append(_gmtPatternSuffix);
+        return buf.toString();
+    }
+
+    /**
+     * Numeric offset field combinations
+     */
+    private enum OffsetFields {
+        H, HM, HMS
+    }
+
+    private String formatOffsetISO8601(int offset, boolean isBasic, boolean useUtcIndicator, boolean isShort, boolean ignoreSeconds) {
+        int absOffset = offset < 0 ? -offset : offset;
+        if (useUtcIndicator && (absOffset < MILLIS_PER_SECOND || (ignoreSeconds && absOffset < MILLIS_PER_MINUTE))) {
+            return ISO8601_UTC;
+        }
+        OffsetFields minFields = isShort ? OffsetFields.H : OffsetFields.HM;
+        OffsetFields maxFields = ignoreSeconds ? OffsetFields.HM : OffsetFields.HMS;
+        Character sep = isBasic ? null : ':';
+
+        // Note: OffsetFields.HMS as maxFields is an ICU extension. ISO 8601 specification does
+        // not support seconds field.
+
+        if (absOffset >= MAX_OFFSET) {
+            throw new IllegalArgumentException("Offset out of range :" + offset);
+        }
+
+        int[] fields = new int[3];
+        fields[0] = absOffset / MILLIS_PER_HOUR;
+        absOffset = absOffset % MILLIS_PER_HOUR;
+        fields[1] = absOffset / MILLIS_PER_MINUTE;
+        absOffset = absOffset % MILLIS_PER_MINUTE;
+        fields[2] = absOffset / MILLIS_PER_SECOND;
+
+        assert(fields[0] >= 0 && fields[0] <= MAX_OFFSET_HOUR);
+        assert(fields[1] >= 0 && fields[1] <= MAX_OFFSET_MINUTE);
+        assert(fields[2] >= 0 && fields[2] <= MAX_OFFSET_SECOND);
+
+        int lastIdx = maxFields.ordinal();
+        while (lastIdx > minFields.ordinal()) {
+            if (fields[lastIdx] != 0) {
+                break;
+            }
+            lastIdx--;
+        }
+
+        StringBuilder buf = new StringBuilder();
+        char sign = '+';
+        if (offset < 0) {
+            // if all output fields are 0s, do not use negative sign
+            for (int idx = 0; idx <= lastIdx; idx++) {
+                if (fields[idx] != 0) {
+                    sign = '-';
+                    break;
+                }
+            }
+        }
+        buf.append(sign);
+
+        for (int idx = 0; idx <= lastIdx; idx++) {
+            if (sep != null && idx != 0) {
+                buf.append(sep);
+            }
+            if (fields[idx] < 10) {
+                buf.append('0');
+            }
+            buf.append(fields[idx]);
+        }
+        return buf.toString();
+    }
 
     /**
      * Private method returning the time zone's specific format string.
@@ -1344,6 +1746,26 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
         return name;
     }
 
+    /**
+     * Private method returning the time zone's exemplar location string.
+     * This method will never return null.
+     * 
+     * @param tz the time zone
+     * @return the time zone's exemplar location name.
+     */
+    private String formatExemplarLocation(TimeZone tz) {
+        String location = getTimeZoneNames().getExemplarLocationName(ZoneMeta.getCanonicalCLDRID(tz));
+        if (location == null) {
+            // Use "unknown" location
+            location = getTimeZoneNames().getExemplarLocationName(UNKNOWN_ZONE_ID);
+            if (location == null) {
+                // last resort
+                location = UNKNOWN_LOCATION;
+            }
+        }
+        return location;
+    }
+
     /**
      * Private method returns a time zone ID. If tzID is not null, the value of tzID is returned.
      * If tzID is null, then this method look up a time zone ID for the current region. This is a
@@ -1484,6 +1906,26 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
         _gmtOffsetPatterns = new String[size];
         System.arraycopy(gmtOffsetPatterns, 0, _gmtOffsetPatterns, 0, size);
         _gmtOffsetPatternItems = gmtOffsetPatternItems;
+        checkAbuttingHoursAndMinutes();
+    }
+
+    private void checkAbuttingHoursAndMinutes() {
+        _abuttingOffsetHoursAndMinutes = false;
+        for (Object[] items : _gmtOffsetPatternItems) {
+            boolean afterH = false;
+            for (Object item : items) {
+                if (item instanceof GMTOffsetField) {
+                    GMTOffsetField fld = (GMTOffsetField)item;
+                    if (afterH) {
+                        _abuttingOffsetHoursAndMinutes = true;
+                    } else if (fld.getType() == 'H') {
+                        afterH = true;
+                    }
+                } else if (afterH) {
+                    break;
+                }
+            }
+        }
     }
 
     /**
@@ -1503,19 +1945,13 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
             return _type;
         }
 
+        @SuppressWarnings("unused")
         int getWidth() {
             return _width;
         }
 
         static boolean isValid(char type, int width) {
-            switch (type) {
-            case 'H':
-                return (width == 1 || width == 2);
-            case 'm':
-            case 's':
-                return (width == 2);
-            }
-            return false;
+            return (width == 1 ||  width == 2);
         }
     }
 
@@ -1623,18 +2059,18 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
 
         return items.toArray(new Object[items.size()]);
     }
+
     /**
-     * Appends second field to the offset pattern with hour/minute
+     * Appends seconds field to the offset pattern with hour/minute
      * 
-     * @param offsetHM the offset pattern including hour and minute fields
-     * @return the offset pattern including hour, minute and second fields
+     * @param offsetHM the offset pattern including hours and minutes fields
+     * @return the offset pattern including hours, minutes and seconds fields
      */
     //TODO This code will be obsoleted once we add hour-minute-second pattern data in CLDR
     private static String expandOffsetPattern(String offsetHM) {
         int idx_mm = offsetHM.indexOf("mm");
         if (idx_mm < 0) {
-            // we cannot do anything with this...
-            return offsetHM + ":ss";
+            throw new RuntimeException("Bad time zone hour pattern data");
         }
         String sep = ":";
         int idx_H = offsetHM.substring(0, idx_mm).lastIndexOf("H");
@@ -1644,6 +2080,29 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
         return offsetHM.substring(0, idx_mm + 2) + sep + "ss" + offsetHM.substring(idx_mm + 2);
     }
 
+    /**
+     * Truncates minutes field from the offset pattern with hour/minute
+     * 
+     * @param offsetHM the offset pattern including hours and minutes fields
+     * @return the offset pattern including only hours field
+     */
+    //TODO This code will be obsoleted once we add hour pattern data in CLDR
+    private static String truncateOffsetPattern(String offsetHM) {
+        int idx_mm = offsetHM.indexOf("mm");
+        if (idx_mm < 0) {
+            throw new RuntimeException("Bad time zone hour pattern data");
+        }
+        int idx_HH = offsetHM.substring(0, idx_mm).lastIndexOf("HH");
+        if (idx_HH >= 0) {
+            return offsetHM.substring(0, idx_HH + 2);
+        }
+        int idx_H = offsetHM.substring(0, idx_mm).lastIndexOf("H");
+        if (idx_H >= 0) {
+            return offsetHM.substring(0, idx_H + 1);
+        }
+        throw new RuntimeException("Bad time zone hour pattern data");
+    }
+
     /**
      * Appends localized digits to the buffer.
      * <p>
@@ -1686,59 +2145,39 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
      * 
      * @param text the text contains a localized GMT offset string at the position.
      * @param pos the position.
+     * @param isShort true if this parser to try the short format first
      * @param hasDigitOffset receiving if the parsed zone string contains offset digits.
      * @return the offset from GMT(UTC) in milliseconds for the given localized GMT
      * offset format string.
      */
-    private int parseOffsetLocalizedGMT(String text, ParsePosition pos, Output<Boolean> hasDigitOffset) {
+    private int parseOffsetLocalizedGMT(String text, ParsePosition pos, boolean isShort, Output<Boolean> hasDigitOffset) {
         int start = pos.getIndex();
-        int idx = start;
-        boolean parsed = false;
         int offset = 0;
+        int[] parsedLength = {0};
 
         if (hasDigitOffset != null) {
             hasDigitOffset.value = false;
         }
 
-        do {
-            // Prefix part
-            int len = _gmtPatternPrefix.length();
-            if (len > 0 && !text.regionMatches(true, idx, _gmtPatternPrefix, 0, len)) {
-                // prefix match failed
-                break;
-            }
-            idx += len;
-
-            // Offset part
-            int[] offsetLen = new int[1];
-            offset = parseOffsetFields(text, idx, false, offsetLen);
-            if (offsetLen[0] == 0) {
-                // offset field match failed
-                break;
-            }
-            idx += offsetLen[0];
-
-            // Suffix part
-            len = _gmtPatternSuffix.length();
-            if (len > 0 && !text.regionMatches(true, idx, _gmtPatternSuffix, 0, len)) {
-                // no suffix match
-                break;
-            }
-            idx += len;
-            parsed = true;
+        offset = parseOffsetLocalizedGMTPattern(text, start, isShort, parsedLength);
 
-        } while (false);
+        // For now, parseOffsetLocalizedGMTPattern handles both long and short
+        // formats, no matter isShort is true or false. This might be changed in future
+        // when strict parsing is necessary, or different set of patterns are used for
+        // short/long formats.
+//        if (parsedLength[0] == 0) {
+//            offset = parseOffsetLocalizedGMTPattern(text, start, !isShort, parsedLength);
+//        }
 
-        if (parsed) {
+        if (parsedLength[0] > 0) {
             if (hasDigitOffset != null) {
                 hasDigitOffset.value = true;
             }
-            pos.setIndex(idx);
+            pos.setIndex(start + parsedLength[0]);
             return offset;
         }
 
         // Try the default patterns
-        int[] parsedLength = {0};
         offset = parseOffsetDefaultLocalizedGMT(text, start, parsedLength);
         if (parsedLength[0] > 0) {
             if (hasDigitOffset != null) {
@@ -1767,97 +2206,186 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
         return 0;
     }
 
+    /**
+     * Parse localized GMT format generated by the pattern used by this formatter, except
+     * GMT Zero format.
+     * @param text the input text
+     * @param start the start index
+     * @param isShort true if the short localized GMT format is parsed.
+     * @param parsedLen the parsed length, or 0 on failure.
+     * @return the parsed offset in milliseconds.
+     */
+    private int parseOffsetLocalizedGMTPattern(String text, int start, boolean isShort, int[] parsedLen) {
+        int idx = start;
+        int offset = 0;
+        boolean parsed = false;
+
+        do {
+            // Prefix part
+            int len = _gmtPatternPrefix.length();
+            if (len > 0 && !text.regionMatches(true, idx, _gmtPatternPrefix, 0, len)) {
+                // prefix match failed
+                break;
+            }
+            idx += len;
+    
+            // Offset part
+            int[] offsetLen = new int[1];
+            offset = parseOffsetFields(text, idx, false, offsetLen);
+            if (offsetLen[0] == 0) {
+                // offset field match failed
+                break;
+            }
+            idx += offsetLen[0];
+    
+            // Suffix part
+            len = _gmtPatternSuffix.length();
+            if (len > 0 && !text.regionMatches(true, idx, _gmtPatternSuffix, 0, len)) {
+                // no suffix match
+                break;
+            }
+            idx += len;
+            parsed = true;
+        } while (false);
+
+        parsedLen[0] = parsed ? idx - start : 0;
+        return offset;
+    }
+
     /**
      * Parses localized GMT offset fields into offset.
      * 
      * @param text the input text
      * @param start the start index
-     * @param minimumHourWidth true if the parser allows hour field width to be 1
+     * @param isShort true if this is a short format - currently not used
      * @param parsedLen the parsed length, or 0 on failure.
      * @return the parsed offset in milliseconds.
      */
-    private int parseOffsetFields(String text, int start, boolean minimumHourWidth, int[] parsedLen) {
+    private int parseOffsetFields(String text, int start, boolean isShort, int[] parsedLen) {
         int outLen = 0;
-        int[] tmpParsedLen = {0};
         int offset = 0;
-        boolean sawVarHourAndAbuttingField = false;
+        int sign = 1;
 
         if (parsedLen != null && parsedLen.length >= 1) {
             parsedLen[0] = 0;
         }
 
+        int offsetH, offsetM, offsetS;
+        offsetH = offsetM = offsetS = 0;
+
+        int[] fields = {0, 0, 0};
         for (GMTOffsetPatternType gmtPatType : PARSE_GMT_OFFSET_TYPES) {
-            int offsetH = 0, offsetM = 0, offsetS = 0;
-            int idx = start;
             Object[] items = _gmtOffsetPatternItems[gmtPatType.ordinal()];
             assert items != null;
 
-            boolean failed = false;
-            for (int i = 0; i < items.length; i++) {
-                if (items[i] instanceof String) {
-                    String patStr = (String)items[i];
-                    int len = patStr.length();
-                    if (!text.regionMatches(true, idx, patStr, 0, len)) {
-                        failed = true;
-                        break;
-                    }
-                    idx += len;
-                } else {
-                    assert(items[i] instanceof GMTOffsetField);
-                    GMTOffsetField field = (GMTOffsetField)items[i];
-                    char fieldType = field.getType();
-                    if (fieldType == 'H') {
-                        int minDigits = 1;
-                        int maxDigits = minimumHourWidth ? 1 : 2;
-                        if (!minimumHourWidth && !sawVarHourAndAbuttingField) {
-                            if (i + 1 < items.length && (items[i + 1] instanceof GMTOffsetField)) {
-                                sawVarHourAndAbuttingField = true;
-                            }
-                        }
-                        offsetH = parseOffsetFieldWithLocalizedDigits(text, idx, minDigits, maxDigits, 0, MAX_OFFSET_HOUR, tmpParsedLen);
-                    } else if (fieldType == 'm') {
-                        offsetM = parseOffsetFieldWithLocalizedDigits(text, idx, 2, 2, 0, MAX_OFFSET_MINUTE, tmpParsedLen);
-                    } else if (fieldType == 's') {
-                        offsetS = parseOffsetFieldWithLocalizedDigits(text, idx, 2, 2, 0, MAX_OFFSET_SECOND, tmpParsedLen);
-                    }
-
-                    if (tmpParsedLen[0] == 0) {
-                        failed = true;
-                        break;
-                    }
-                    idx += tmpParsedLen[0];
-                }
-            }
-            if (!failed) {
-                int sign = gmtPatType.isPositive() ? 1 : -1;
-                offset = ((((offsetH * 60) + offsetM) * 60) + offsetS) * 1000 * sign;
-                outLen = idx - start;
+            outLen = parseOffsetFieldsWithPattern(text, start, items, false, fields);
+            if (outLen > 0) {
+                sign = gmtPatType.isPositive() ? 1 : -1;
+                offsetH = fields[0];
+                offsetM = fields[1];
+                offsetS = fields[2];
                 break;
             }
         }
-
-        if (outLen == 0 && sawVarHourAndAbuttingField && !minimumHourWidth) {
-            // When hour field is variable width and another non-literal pattern
-            // field follows, the parse loop above might eat up the digit from
-            // the abutting field. For example, with pattern "-Hmm" and input "-100",
-            // the hour is parsed as -10 and fails to parse minute field.
-            //
-            // If this is the case, try parsing the text one more time with the arg
-            // minimumHourWidth = true
-            //
-            // Note: This fallback is not applicable when quitAtHourField is true, because
-            // the option is designed for supporting the case like "GMT+5". In this case,
-            // we should get better result for parsing hour digits as much as possible.
-
-            return parseOffsetFields(text, start, true, parsedLen);
+        if (outLen > 0 && _abuttingOffsetHoursAndMinutes) {
+            // When hours field is abutting minutes field,
+            // the parse result above may not be appropriate.
+            // For example, "01020" is parsed as 01:02 above,
+            // but it should be parsed as 00:10:20.
+            int tmpLen = 0;
+            int tmpSign = 1;
+            for (GMTOffsetPatternType gmtPatType : PARSE_GMT_OFFSET_TYPES) {
+                Object[] items = _gmtOffsetPatternItems[gmtPatType.ordinal()];
+                assert items != null;
+
+                // forcing parse to use single hour digit
+                tmpLen = parseOffsetFieldsWithPattern(text, start, items, true, fields);
+                if (tmpLen > 0) {
+                    tmpSign = gmtPatType.isPositive() ? 1 : -1;
+                    break;
+                }
+            }
+            if (tmpLen > outLen) {
+                // Better parse result with single hour digit
+                outLen = tmpLen;
+                sign = tmpSign;
+                offsetH = fields[0];
+                offsetM = fields[1];
+                offsetS = fields[2];
+            }
         }
 
         if (parsedLen != null && parsedLen.length >= 1) {
             parsedLen[0] = outLen;
         }
+
+        if (outLen > 0) {
+            offset = ((((offsetH * 60) + offsetM) * 60) + offsetS) * 1000 * sign;
+        }
+
         return offset;
     }
 
+    /**
+     * Parses localized GMT offset fields with the given pattern
+     * 
+     * @param text the input text
+     * @param start the start index
+     * @param patternItems the pattern (already itemized)
+     * @param forceSingleHourDigit true if hours field is parsed as a single digit
+     * @param fields receives the parsed hours/minutes/seconds
+     * @return parsed length
+     */
+    private int parseOffsetFieldsWithPattern(String text, int start, Object[] patternItems, boolean forceSingleHourDigit, int fields[]) {
+        assert (fields != null && fields.length >= 3);
+        fields[0] = fields[1] = fields[2] = 0;
+
+        boolean failed = false;
+        int offsetH, offsetM, offsetS;
+        offsetH = offsetM = offsetS = 0;
+        int idx = start;
+        int[] tmpParsedLen = {0};
+        for (int i = 0; i < patternItems.length; i++) {
+            if (patternItems[i] instanceof String) {
+                String patStr = (String)patternItems[i];
+                int len = patStr.length();
+                if (!text.regionMatches(true, idx, patStr, 0, len)) {
+                    failed = true;
+                    break;
+                }
+                idx += len;
+            } else {
+                assert(patternItems[i] instanceof GMTOffsetField);
+                GMTOffsetField field = (GMTOffsetField)patternItems[i];
+                char fieldType = field.getType();
+                if (fieldType == 'H') {
+                    int maxDigits = forceSingleHourDigit ? 1 : 2;
+                    offsetH = parseOffsetFieldWithLocalizedDigits(text, idx, 1, maxDigits, 0, MAX_OFFSET_HOUR, tmpParsedLen);
+                } else if (fieldType == 'm') {
+                    offsetM = parseOffsetFieldWithLocalizedDigits(text, idx, 2, 2, 0, MAX_OFFSET_MINUTE, tmpParsedLen);
+                } else if (fieldType == 's') {
+                    offsetS = parseOffsetFieldWithLocalizedDigits(text, idx, 2, 2, 0, MAX_OFFSET_SECOND, tmpParsedLen);
+                }
+
+                if (tmpParsedLen[0] == 0) {
+                    failed = true;
+                    break;
+                }
+                idx += tmpParsedLen[0];
+            }
+        }
+
+        if (failed) {
+            return 0;
+        }
+
+        fields[0] = offsetH;
+        fields[1] = offsetM;
+        fields[2] = offsetS;
+
+        return idx - start;
+    }
+
     /**
      * Parses the input text using the default format patterns (e.g. "UTC{0}").
      * @param text the input text
@@ -2157,12 +2685,12 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
 
 
     /**
-     * Returns offset from GMT(UTC) in milliseconds for the given ISO 8601 style
-     * (extended format) time zone string. When the given string is not an ISO 8601 time
+     * Returns offset from GMT(UTC) in milliseconds for the given ISO 8601 time zone string
+     * (basic format, extended format, or UTC indicator). When the given string is not an ISO 8601 time
      * zone string, this method sets the current position as the error index
      * to <code>ParsePosition pos</code> and returns 0.
      * 
-     * @param text the text contains ISO 8601 style time zone string (e.g. "-08:00", "Z")
+     * @param text the text contains ISO 8601 style time zone string (e.g. "-08", "-08:00", "Z")
      * at the position.
      * @param pos the position.
      * @param extendedOnly <code>true</code> if parsing the text as ISO 8601 extended offset format (e.g. "-08:00"),
@@ -2171,7 +2699,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
      * @return the offset from GMT(UTC) in milliseconds for the given ISO 8601 style
      * time zone string.
      */
-    private int parseOffsetISO8601(String text, ParsePosition pos, boolean extendedOnly, Output<Boolean> hasDigitOffset) {
+    private static int parseOffsetISO8601(String text, ParsePosition pos, boolean extendedOnly, Output<Boolean> hasDigitOffset) {
         if (hasDigitOffset != null) {
             hasDigitOffset.value = false;
         }
@@ -2199,7 +2727,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
             return 0;
         }
         ParsePosition posOffset = new ParsePosition(start + 1);
-        int offset = parseAsciiOffsetFields(text, posOffset, ':', OffsetFields.H, OffsetFields.HMS, false);
+        int offset = parseAsciiOffsetFields(text, posOffset, ':', OffsetFields.H, OffsetFields.HMS);
         if (posOffset.getErrorIndex() == -1 && !extendedOnly && (posOffset.getIndex() - start <= 3)) {
             // If the text is successfully parsed as extended format with the options above, it can be also parsed
             // as basic format. For example, "0230" can be parsed as offset 2:00 (only first digits are valid for
@@ -2224,69 +2752,6 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
         return sign * offset;
     }
 
-    /**
-     * Numeric offset field combinations
-     */
-    private enum OffsetFields {
-        H, HM, HMS
-    }
-
-    /**
-     * Formats offset using ASCII digits
-     * @param offset The offset
-     * @param sep The field separator character or null if not required
-     * @param minFields The minimum fields
-     * @param maxFields The maximum fields
-     * @return The offset string
-     * @throws IllegalArgumentException if the specified offset is out of supported range
-     * (-24 hours &lt; offset &lt; +24 hours).
-     */
-    private static String formatOffsetWithAsciiDigits(int offset, Character sep, OffsetFields minFields, OffsetFields maxFields) {
-        assert maxFields.ordinal() >= minFields.ordinal();
-
-        if (Math.abs(offset) >= MAX_OFFSET) {
-            throw new IllegalArgumentException("Offset out of range :" + offset);
-        }
-
-        StringBuilder buf = new StringBuilder();
-        char sign = '+';
-        if (offset < 0) {
-            sign = '-';
-            offset = -offset;
-        }
-        buf.append(sign);
-
-        int[] fields = new int[3];
-        fields[0] = offset / MILLIS_PER_HOUR;
-        offset = offset % MILLIS_PER_HOUR;
-        fields[1] = offset / MILLIS_PER_MINUTE;
-        offset = offset % MILLIS_PER_MINUTE;
-        fields[2] = offset / MILLIS_PER_SECOND;
-
-        assert(fields[0] >= 0 && fields[0] <= MAX_OFFSET_HOUR);
-        assert(fields[1] >= 0 && fields[1] <= MAX_OFFSET_MINUTE);
-        assert(fields[2] >= 0 && fields[2] <= MAX_OFFSET_SECOND);
-
-        int lastIdx = maxFields.ordinal();
-        while (lastIdx > minFields.ordinal()) {
-            if (fields[lastIdx] != 0) {
-                break;
-            }
-            lastIdx--;
-        }
-
-        for (int idx = 0; idx <= lastIdx; idx++) {
-            if (sep != null && idx != 0) {
-                buf.append(sep);
-            }
-            if (fields[idx] < 10) {
-                buf.append('0');
-            }
-            buf.append(fields[idx]);
-        }
-        return buf.toString();
-    }
-
     /**
      * Parses offset represented by contiguous ASCII digits
      * <p>
@@ -2297,7 +2762,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
      * @param pos The parse position
      * @param minFields The minimum Fields to be parsed
      * @param maxFields The maximum Fields to be parsed
-     * @param fixedHourWidth true if hour field must be width of 2
+     * @param fixedHourWidth true if hours field must be width of 2
      * @return Parsed offset, 0 or positive number.
      */
     private static int parseAbuttingAsciiOffsetFields(String text, ParsePosition pos,
@@ -2390,29 +2855,34 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
      * @param sep The separator character
      * @param minFields The minimum Fields to be parsed
      * @param maxFields The maximum Fields to be parsed
-     * @param fixedHourWidth true if hour field must be width of 2
      * @return Parsed offset, 0 or positive number.
      */
-    private static int parseAsciiOffsetFields(String text, ParsePosition pos,
-            char sep, OffsetFields minFields, OffsetFields maxFields, boolean fixedHourWidth) {
+    private static int parseAsciiOffsetFields(String text, ParsePosition pos, char sep,
+            OffsetFields minFields, OffsetFields maxFields) {
         int start = pos.getIndex();
         int[] fieldVal = {0, 0, 0};
         int[] fieldLen = {0, -1, -1};
         for (int idx = start, fieldIdx = 0; idx < text.length() && fieldIdx <= maxFields.ordinal(); idx++) {
             char c = text.charAt(idx);
             if (c == sep) {
-                if (fieldLen[fieldIdx] < 0) {
-                    // next field - expected
-                    fieldLen[fieldIdx] = 0;
-                } else if (fieldIdx == 0 && !fixedHourWidth) {
+                if (fieldIdx == 0) {
+                    if (fieldLen[0] == 0) {
+                        // no hours field
+                        break;
+                    }
                     // 1 digit hour, move to next field
                     fieldIdx++;
-                    fieldLen[fieldIdx] = 0;
                 } else {
-                    // otherwise, premature field
-                    break;
+                    if (fieldLen[fieldIdx] != -1) {
+                        // premature minutes or seconds field
+                        break;
+                    }
+                    fieldLen[fieldIdx] = 0;
                 }
                 continue;
+            } else if (fieldLen[fieldIdx] == -1) {
+                // no separator after 2 digit field
+                break;
             }
             int digit = ASCII_DIGITS.indexOf(c);
             if (digit < 0) {
@@ -2432,13 +2902,10 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
         OffsetFields parsedFields = null;
         do {
             // hour
-            if (fieldLen[0] == 0 || (fieldLen[0] == 1 && fixedHourWidth)) {
+            if (fieldLen[0] == 0) {
                 break;
             }
             if (fieldVal[0] > MAX_OFFSET_HOUR) {
-                if (fixedHourWidth) {
-                    break;
-                }
                 offset = (fieldVal[0] / 10) * MILLIS_PER_HOUR;
                 parsedFields = OffsetFields.H;
                 parsedLen = 1;
@@ -2474,6 +2941,115 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
         return offset;
     }
 
+    /**
+     * Parse a zone ID.
+     * @param text the text contains a time zone ID string at the position.
+     * @param pos the position.
+     * @return The zone ID parsed.
+     */
+    private static String parseZoneID(String text, ParsePosition pos) {
+        String resolvedID = null;
+        if (ZONE_ID_TRIE == null) {
+            synchronized (TimeZoneFormat.class) {
+                if (ZONE_ID_TRIE == null) {
+                    // Build zone ID trie
+                    TextTrieMap<String> trie = new TextTrieMap<String>(true);
+                    String[] ids = TimeZone.getAvailableIDs();
+                    for (String id : ids) {
+                        trie.put(id, id);
+                    }
+                    ZONE_ID_TRIE = trie;
+                }
+            }
+        }
+
+        int[] matchLen = new int[] {0};
+        Iterator<String> itr = ZONE_ID_TRIE.get(text, pos.getIndex(), matchLen);
+        if (itr != null) {
+            resolvedID = itr.next();
+            pos.setIndex(pos.getIndex() + matchLen[0]);
+        } else {
+            // TODO
+            // We many need to handle rule based custom zone ID (See ZoneMeta.parseCustomID),
+            // such as GM+05:00. However, the public parse method in this class also calls
+            // parseOffsetLocalizedGMT and custom zone IDs are likely supported by the parser,
+            // so we might not need to handle them here.
+            pos.setErrorIndex(pos.getIndex());
+        }
+        return resolvedID;
+    }
+
+    /**
+     * Parse a short zone ID.
+     * @param text the text contains a time zone ID string at the position.
+     * @param pos the position.
+     * @return The zone ID for the parsed short zone ID.
+     */
+    private static String parseShortZoneID(String text, ParsePosition pos) {
+        String resolvedID = null;
+        if (SHORT_ZONE_ID_TRIE == null) {
+            synchronized (TimeZoneFormat.class) {
+                if (SHORT_ZONE_ID_TRIE == null) {
+                    // Build short zone ID trie
+                    TextTrieMap<String> trie = new TextTrieMap<String>(true);
+                    Set<String> canonicalIDs = TimeZone.getAvailableIDs(SystemTimeZoneType.CANONICAL, null, null);
+                    for (String id : canonicalIDs) {
+                        String shortID = ZoneMeta.getShortID(id);
+                        if (shortID != null) {
+                            trie.put(shortID, id);
+                        }
+                    }
+                    // Canonical list does not contain Etc/Unknown
+                    trie.put(UNKNOWN_SHORT_ZONE_ID, UNKNOWN_ZONE_ID);
+                    SHORT_ZONE_ID_TRIE = trie;
+                }
+            }
+        }
+
+        int[] matchLen = new int[] {0};
+        Iterator<String> itr = SHORT_ZONE_ID_TRIE.get(text, pos.getIndex(), matchLen);
+        if (itr != null) {
+            resolvedID = itr.next();
+            pos.setIndex(pos.getIndex() + matchLen[0]);
+        } else {
+            pos.setErrorIndex(pos.getIndex());
+        }
+
+        return resolvedID;
+    }
+
+    /**
+     * Parse an exemplar location string.
+     * @param text the text contains an exemplar location string at the position.
+     * @param pos the position.
+     * @return The zone ID for the parsed exemplar location.
+     */
+    private String parseExemplarLocation(String text, ParsePosition pos) {
+        int startIdx = pos.getIndex();
+        int parsedPos = -1;
+        String tzID = null;
+
+        EnumSet<NameType> nameTypes = EnumSet.of(NameType.EXEMPLAR_LOCATION);
+        Collection<MatchInfo> exemplarMatches = _tznames.find(text, startIdx, nameTypes);
+        if (exemplarMatches != null) {
+            MatchInfo exemplarMatch = null;
+            for (MatchInfo match : exemplarMatches) {
+                if (startIdx + match.matchLength() > parsedPos) {
+                    exemplarMatch = match;
+                    parsedPos = startIdx + match.matchLength();
+                }
+            }
+            if (exemplarMatch != null) {
+                tzID = getTimeZoneID(exemplarMatch.tzID(), exemplarMatch.mzID());
+                pos.setIndex(parsedPos);
+            }
+        }
+        if (tzID == null) {
+            pos.setErrorIndex(startIdx);
+        }
+
+        return tzID;
+    }
 
     /**
      * Implements <code>TimeZoneFormat</code> object cache
@@ -2560,12 +3136,22 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
             throw new InvalidObjectException("Missing field: gmtPattern");
         }
 
-        _gmtOffsetPatterns = (String[])fields.get("_gmtOffsetPatterns", null);
-        if (_gmtOffsetPatterns == null) {
+        String[] tmpGmtOffsetPatterns = (String[])fields.get("_gmtOffsetPatterns", null);
+        if (tmpGmtOffsetPatterns == null) {
             throw new InvalidObjectException("Missing field: gmtOffsetPatterns");
-        } else if (_gmtOffsetPatterns.length < 4) {
+        } else if (tmpGmtOffsetPatterns.length < 4) {
             throw new InvalidObjectException("Incompatible field: gmtOffsetPatterns");
         }
+        _gmtOffsetPatterns = new String[6];
+        if (tmpGmtOffsetPatterns.length == 4) {
+            for (int i = 0; i < 4; i++) {
+                _gmtOffsetPatterns[i] = tmpGmtOffsetPatterns[i];
+            }
+            _gmtOffsetPatterns[GMTOffsetPatternType.POSITIVE_H.ordinal()] = truncateOffsetPattern(_gmtOffsetPatterns[GMTOffsetPatternType.POSITIVE_HM.ordinal()]);
+            _gmtOffsetPatterns[GMTOffsetPatternType.NEGATIVE_H.ordinal()] = truncateOffsetPattern(_gmtOffsetPatterns[GMTOffsetPatternType.NEGATIVE_HM.ordinal()]);
+        } else {
+            _gmtOffsetPatterns = tmpGmtOffsetPatterns;
+        }
 
         _gmtOffsetDigits = (String[])fields.get("_gmtOffsetDigits", null);
         if (_gmtOffsetDigits == null) {
index fb7c4a78641e35e77a432f8714dce94b8b3e8a30..febe69a8c7accbce363d996beba6d07a2e6fc311 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *******************************************************************************
- * Copyright (C) 2011, International Business Machines Corporation and         *
+ * Copyright (C) 2011-2013, International Business Machines Corporation and    *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  */
@@ -11,10 +11,10 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.Set;
-import java.util.regex.Pattern;
 
 import com.ibm.icu.impl.ICUConfig;
 import com.ibm.icu.impl.SoftCache;
+import com.ibm.icu.impl.TimeZoneNamesImpl;
 import com.ibm.icu.util.TimeZone;
 import com.ibm.icu.util.ULocale;
 
@@ -119,6 +119,13 @@ public abstract class TimeZoneNames implements Serializable {
          * @provisional This API might change or be removed in a future release.
          */
         SHORT_DAYLIGHT,
+        /**
+         * Exemplar location name, such as "Los Angeles".
+         * 
+         * @draft ICU 51
+         * @provisional This API might change or be removed in a future release.
+         */
+        EXEMPLAR_LOCATION,
     }
 
     private static Cache TZNAMES_CACHE = new Cache();
@@ -126,7 +133,6 @@ public abstract class TimeZoneNames implements Serializable {
     private static final Factory TZNAMES_FACTORY;
     private static final String FACTORY_NAME_PROP = "com.ibm.icu.text.TimeZoneNames.Factory.impl";
     private static final String DEFAULT_FACTORY_CLASS = "com.ibm.icu.impl.TimeZoneNamesFactoryImpl";
-    private static final Pattern LOC_EXCLUSION_PATTERN = Pattern.compile("Etc/.*|SystemV/.*|.*/Riyadh8[7-9]");
 
     static {
         Factory factory = null;
@@ -295,17 +301,7 @@ public abstract class TimeZoneNames implements Serializable {
      * @provisional This API might change or be removed in a future release.
      */
     public String getExemplarLocationName(String tzID) {
-        if (tzID == null || tzID.length() == 0 || LOC_EXCLUSION_PATTERN.matcher(tzID).matches()) {
-            return null;
-        }
-
-        String location = null;
-        int sep = tzID.lastIndexOf('/');
-        if (sep > 0 && sep + 1 < tzID.length()) {
-            location = tzID.substring(sep + 1).replace('_', ' ');
-        }
-
-        return location;
+        return TimeZoneNamesImpl.getDefaultExemplarLocationName(tzID);
     }
 
     /**
index fc0414145c3ef404f55248a8d6a6690dfd47a04b..827a8981fc5e13b73c3b3d2c5106c24168e14b67 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * @(#)TimeZone.java    1.51 00/01/19
  *
- * Copyright (C) 1996-2012, International Business Machines
+ * Copyright (C) 1996-2013, International Business Machines
  * Corporation and others.  All Rights Reserved.
  */
 
@@ -561,7 +561,8 @@ abstract public class TimeZone implements Serializable, Cloneable, Freezable<Tim
             if (daylight && timeType.value == TimeType.STANDARD ||
                     !daylight && timeType.value == TimeType.DAYLIGHT) {
                 int offset = daylight ? getRawOffset() + getDSTSavings() : getRawOffset();
-                result = tzfmt.formatOffsetLocalizedGMT(offset);
+                result = (style == SHORT_GENERIC) ?
+                        tzfmt.formatOffsetShortLocalizedGMT(offset) : tzfmt.formatOffsetLocalizedGMT(offset);
             }
 
         } else if (style == LONG_GMT || style == SHORT_GMT) {
@@ -573,7 +574,7 @@ abstract public class TimeZone implements Serializable, Cloneable, Freezable<Tim
                 result = tzfmt.formatOffsetLocalizedGMT(offset);
                 break;
             case SHORT_GMT:
-                result = tzfmt.formatOffsetRFC822(offset);
+                result = tzfmt.formatOffsetISO8601Basic(offset, false, false, false);
                 break;
             }
         } else {
@@ -598,7 +599,8 @@ abstract public class TimeZone implements Serializable, Cloneable, Freezable<Tim
                 // Fallback to localized GMT
                 TimeZoneFormat tzfmt = TimeZoneFormat.getInstance(locale);
                 int offset = daylight && useDaylightTime() ? getRawOffset() + getDSTSavings() : getRawOffset();
-                result = tzfmt.formatOffsetLocalizedGMT(offset);
+                result = (style == LONG) ?
+                        tzfmt.formatOffsetLocalizedGMT(offset) : tzfmt.formatOffsetShortLocalizedGMT(offset);
             }
         }
         assert(result != null);
index 0e35a4b03e8e2ba2f1380b0e8c310e518fb3a1ba..adf34d4f31aa2841751f6f8e9781da5999c24304 100644 (file)
@@ -339,18 +339,25 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         // Expected output field values for above DateFormats on aug13
         // Fields are given in order of DateFormat field number
         final String EXPECTED[] = {
-             "", "1997", "August", "13", "", "", "34", "12", "",
-            "Wednesday", "", "", "", "", "PM", "2", "", "Pacific Daylight Time", "", "", "", "", "", "", "","","","","","","",
-
-            "", "1997", "ao\u00FBt", "13", "", "14", "34", "12", "",
-            "mercredi", "", "", "", "", "", "", "", "heure avanc\u00E9e du Pacifique", "", "", "", "", "", "", "","","","","","","",
-
-            "AD", "1997", "8", "13", "14", "14", "34", "12", "5",
-            "Wed", "225", "2", "33", "3", "PM", "2", "2", "PDT", "1997", "4", "1997", "2450674", "52452513", "-0700", "PT","4","8","3","3","PDT","1997",
-
-            "Anno Domini", "1997", "August", "0013", "0014", "0014", "0034", "0012", "5130",
-            "Wednesday", "0225", "0002", "0033", "0003", "PM", "0002", "0002", "Pacific Daylight Time", "1997",
-            "Wednesday", "1997", "2450674", "52452513", "GMT-07:00", "Pacific Time","Wednesday","August", "3rd quarter", "3rd quarter","Los Angeles Time","1997",
+             "", "1997", "August", "13", "", "", "34", "12", "", "Wednesday",
+             "", "", "", "", "PM", "2", "", "Pacific Daylight Time", "", "",
+             "", "", "", "", "", "", "", "", "", "",
+             "", "", "", "",
+
+             "", "1997", "ao\u00FBt", "13", "", "14", "34", "12", "", "mercredi",
+             "", "", "", "", "", "", "", "heure avanc\u00E9e du Pacifique", "", "",
+             "", "", "", "", "", "", "", "", "", "",
+             "", "", "", "",
+
+            "AD", "1997", "8", "13", "14", "14", "34", "12", "5", "Wed",
+            "225", "2", "33", "3", "PM", "2", "2", "PDT", "1997", "4",
+            "1997", "2450674", "52452513", "-0700", "PT", "4", "8", "3", "3", "uslax",
+            "1997", "GMT-7", "-07", "-07",
+
+            "Anno Domini", "1997", "August", "0013", "0014", "0014", "0034", "0012", "5130", "Wednesday",
+            "0225", "0002", "0033", "0003", "PM", "0002", "0002", "Pacific Daylight Time", "1997", "Wednesday",
+            "1997", "2450674", "52452513", "GMT-07:00", "Pacific Time", "Wednesday", "August", "3rd quarter", "3rd quarter", "Los Angeles Time",
+            "1997", "GMT-07:00", "-0700", "-0700",
         };
 
         assertTrue("data size", EXPECTED.length == COUNT * DateFormat.FIELD_COUNT);
@@ -453,7 +460,7 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
     /**
      * This MUST be kept in sync with DateFormatSymbols.patternChars.
      */
-    static final String PATTERN_CHARS = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVU";
+    static final String PATTERN_CHARS = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXx";
 
     /**
      * A list of the DateFormat.Field.
@@ -491,6 +498,9 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         DateFormat.Field.QUARTER,       // q
         DateFormat.Field.TIME_ZONE,     // V
         DateFormat.Field.YEAR,          // U
+        DateFormat.Field.TIME_ZONE,     // O
+        DateFormat.Field.TIME_ZONE,     // X
+        DateFormat.Field.TIME_ZONE,     // x
     };
 
     /**
@@ -529,6 +539,9 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         "STAND_ALONE_QUARTER_FIELD",
         "TIMEZONE_SPECIAL_FIELD",
         "YEAR_NAME_FIELD",
+        "TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD",
+        "TIMEZONE_ISO_FIELD",
+        "TIMEZONE_ISO_LOCAL_FIELD",
     };
 
     /**
@@ -723,26 +736,22 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
         { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZZ", "-08:00", "-8:00" },
         { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "PST", "America/Los_Angeles" },
-        { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "V", "PST", "America/Los_Angeles" },
         { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Pacific Standard Time", "America/Los_Angeles" },
         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "PDT", "America/Los_Angeles" },
-        { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "V", "PDT", "America/Los_Angeles" },
         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Pacific Daylight Time", "America/Los_Angeles" },
         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "PT", "America/Los_Angeles" },
         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Pacific Time", "America/Los_Angeles" },
         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "Los Angeles Time", "America/Los_Angeles" },
-        { "en_GB", "America/Los_Angeles", "2004-01-15T12:00:00Z", "z", "GMT-08:00", "America/Los_Angeles" },
+        { "en_GB", "America/Los_Angeles", "2004-01-15T12:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
         { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "Z", "-0700", "-7:00" },
         { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
         { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "z", "MST", "America/Phoenix" },
-        { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "V", "MST", "America/Phoenix" },
         { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "z", "MST", "America/Phoenix" },
-        { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "V", "MST", "America/Phoenix" },
         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "v", "MST", "America/Phoenix" },
         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "vvvv", "Mountain Standard Time", "America/Phoenix" },
@@ -750,13 +759,11 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
-        { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "V", "GMT-03:00", "-3:00" },
+        { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
-        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "V", "GMT-03:00", "-3:00" },
+        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
@@ -764,13 +771,11 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
-        { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "V", "GMT-03:00", "-3:00" },
+        { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
-        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "V", "GMT-03:00", "-3:00" },
+        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
@@ -778,13 +783,11 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "en", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
         { "en", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
-        { "en", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-05:00", "-5:00" },
-        { "en", "America/Havana", "2004-01-15T00:00:00Z", "V", "GMT-05:00", "-5:00" },
+        { "en", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
         { "en", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Cuba Standard Time", "-5:00" },
         { "en", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
         { "en", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
-        { "en", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-04:00", "-4:00" },
-        { "en", "America/Havana", "2004-07-15T00:00:00Z", "V", "GMT-04:00", "-4:00" },
+        { "en", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
         { "en", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Cuba Daylight Time", "-4:00" },
         { "en", "America/Havana", "2004-07-15T00:00:00Z", "v", "Cuba Time", "America/Havana" },
         { "en", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Cuba Time", "America/Havana" },
@@ -792,13 +795,11 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
         { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
-        { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11:00", "+11:00" },
-        { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "V", "GMT+11:00", "+11:00" },
+        { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
         { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
-        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10:00", "+10:00" },
-        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "V", "GMT+10:00", "+10:00" },
+        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
@@ -806,13 +807,11 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
         { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
-        { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11:00", "+11:00" },
-        { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "V", "GMT+11:00", "+11:00" },
+        { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
         { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
-        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10:00", "+10:00" },
-        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "V", "GMT+10:00", "+10:00" },
+        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
@@ -821,12 +820,10 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         { "en", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
         { "en", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
         { "en", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
-        { "en", "Europe/London", "2004-01-15T00:00:00Z", "V", "GMT", "+0:00" },
         { "en", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Greenwich Mean Time", "+0:00" },
         { "en", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
         { "en", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
-        { "en", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+01:00", "Europe/London" },
-        { "en", "Europe/London", "2004-07-15T00:00:00Z", "V", "GMT+01:00", "Europe/London" },
+        { "en", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "Europe/London" },
         { "en", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "British Summer Time", "Europe/London" },
     // icu en.txt has exemplar city for this time zone
         { "en", "Europe/London", "2004-07-15T00:00:00Z", "v", "United Kingdom Time", "Europe/London" },
@@ -835,25 +832,23 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
-        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-03:00", "-3:00" },
+        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
 
         // JB#5150
         { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
         { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
-        { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+05:30", "+5:30" },
-        { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "V", "GMT+05:30", "+5:30" },
+        { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
         { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
-        { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+05:30", "+05:30" },
-        { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "V", "GMT+05:30", "+05:30" },
+        { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "India Time", "Asia/Calcutta" },
         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "India Standard Time", "Asia/Calcutta" },
@@ -866,44 +861,44 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
         { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
-        { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-08:00", "-8:00" },
+        { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
         { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\u00fcsten-Normalzeit", "-8:00" },
         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
-        { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-07:00", "-7:00" },
+        { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\u00fcsten-Sommerzeit", "-7:00" },
         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles Zeit", "America/Los_Angeles" },
         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Nordamerikanische Westk\u00fcstenzeit", "America/Los_Angeles" },
 
         { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
 
         { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
 
         { "de", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
         { "de", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
-        { "de", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-05:00", "-5:00" },
+        { "de", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
         { "de", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Kubanische Normalzeit", "-5:00" },
         { "de", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
         { "de", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
-        { "de", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-04:00", "-4:00" },
+        { "de", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
         { "de", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Kubanische Sommerzeit", "-4:00" },
         { "de", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
         { "de", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
@@ -913,22 +908,22 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
         { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
-        { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11:00", "+11:00" },
+        { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
         { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
-        { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10:00", "+10:00" },
+        { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
 
         { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
         { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
-        { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11:00", "+11:00" },
+        { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
         { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
-        { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10:00", "+10:00" },
+        { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
@@ -939,30 +934,30 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         { "de", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Mittlere Greenwich-Zeit", "+0:00" },
         { "de", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
         { "de", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
-        { "de", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+01:00", "+1:00" },
+        { "de", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
         { "de", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "Britische Sommerzeit", "+1:00" },
         { "de", "Europe/London", "2004-07-15T00:00:00Z", "v", "Vereinigtes K\u00f6nigreich Zeit", "Europe/London" },
         { "de", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "Vereinigtes K\u00f6nigreich Zeit", "Europe/London" },
 
         { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
-        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-03:00", "-3:00" },
+        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
 
         // JB#5150
         { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
         { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
-        { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+05:30", "+5:30" },
+        { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
         { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
-        { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+05:30", "+05:30" },
+        { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "Indien Zeit", "Asia/Calcutta" },
         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "Indische Zeit", "Asia/Calcutta" },
@@ -971,11 +966,11 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
         { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"-0800", "-8:00" },
-        { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", GMT_ZH+"-0800", "America/Los_Angeles" },
+        { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", GMT_ZH+"-8", "America/Los_Angeles" },
         { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\u5317\u7f8e\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4", "America/Los_Angeles" },
         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"-0700", "-7:00" },
-        { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", GMT_ZH+"-0700", "America/Los_Angeles" },
+        { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", GMT_ZH+"-7", "America/Los_Angeles" },
         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\u5317\u7f8e\u592a\u5e73\u6d0b\u590f\u4ee4\u65f6\u95f4", "America/Los_Angeles" },
     // icu zh.txt has exemplar city for this time zone
         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\u6D1B\u6749\u77F6\u65F6\u95F4", "America/Los_Angeles" },
@@ -983,11 +978,11 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"-0300", "-3:00" },
-        { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", GMT_ZH+"-0300", "-3:00" },
+        { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", GMT_ZH+"-3", "-3:00" },
         { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u963f\u6839\u5ef7\u6807\u51c6\u65f6\u95f4", "-3:00" },
         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"-0300", "-3:00" },
-        { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", GMT_ZH+"-0300", "-3:00" },
+        { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", GMT_ZH+"-3", "-3:00" },
         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u963f\u6839\u5ef7\u6807\u51c6\u65f6\u95f4", "-3:00" },
     // icu zh.txt does not have info for this time zone
         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u5E03\u5B9C\u8BFA\u65AF\u827E\u5229\u65AF\u65F6\u95F4", "America/Buenos_Aires" },
@@ -995,44 +990,44 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"-0300", "-3:00" },
-        { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", GMT_ZH+"-0300", "-3:00" },
+        { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", GMT_ZH+"-3", "-3:00" },
         { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u963f\u6839\u5ef7\u6807\u51c6\u65f6\u95f4", "-3:00" },
         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"-0300", "-3:00" },
-        { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", GMT_ZH+"-0300", "-3:00" },
+        { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", GMT_ZH+"-3", "-3:00" },
         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u963f\u6839\u5ef7\u6807\u51c6\u65f6\u95f4", "-3:00" },
         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u5E03\u5B9C\u8BFA\u65AF\u827E\u5229\u65AF\u65F6\u95F4", "America/Buenos_Aires" },
         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\u963f\u6839\u5ef7\u6807\u51c6\u65f6\u95f4", "America/Buenos_Aires" },
 
         { "zh", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
         { "zh", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"-0500", "-5:00" },
-        { "zh", "America/Havana", "2004-01-15T00:00:00Z", "z", GMT_ZH+"-0500", "-5:00" },
+        { "zh", "America/Havana", "2004-01-15T00:00:00Z", "z", GMT_ZH+"-5", "-5:00" },
         { "zh", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\u53e4\u5df4\u6807\u51c6\u65f6\u95f4", "-5:00" },
         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"-0400", "-4:00" },
-        { "zh", "America/Havana", "2004-07-15T00:00:00Z", "z", GMT_ZH+"-0400", "-4:00" },
+        { "zh", "America/Havana", "2004-07-15T00:00:00Z", "z", GMT_ZH+"-4", "-4:00" },
         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\u53e4\u5df4\u590f\u4ee4\u65f6\u95f4", "-4:00" },
         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "v", "\u53e4\u5df4\u65f6\u95f4", "America/Havana" },
         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\u53e4\u5df4\u65f6\u95f4", "America/Havana" },
 
         { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
         { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"+1100", "+11:00" },
-        { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "z", GMT_ZH+"+1100", "+11:00" },
+        { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "z", GMT_ZH+"+11", "+11:00" },
         { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\u6fb3\u5927\u5229\u4e9a\u4e1c\u90e8\u590f\u4ee4\u65f6\u95f4", "+11:00" },
         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"+1000", "+10:00" },
-        { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "z", GMT_ZH+"+1000", "+10:00" },
+        { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "z", GMT_ZH+"+10", "+10:00" },
         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\u6fb3\u5927\u5229\u4e9a\u4e1c\u90e8\u6807\u51c6\u65f6\u95f4", "+10:00" },
         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\u6089\u5C3C\u65F6\u95F4", "Australia/Sydney" },
         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\u6fb3\u5927\u5229\u4e9a\u4e1c\u90e8\u65f6\u95f4", "Australia/Sydney" },
 
         { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
         { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"+1100", "+11:00" },
-        { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", GMT_ZH+"+1100", "+11:00" },
+        { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", GMT_ZH+"+11", "+11:00" },
         { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\u6fb3\u5927\u5229\u4e9a\u4e1c\u90e8\u590f\u4ee4\u65f6\u95f4", "+11:00" },
         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"+1000", "+10:00" },
-        { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", GMT_ZH+"+1000", "+10:00" },
+        { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", GMT_ZH+"+10", "+10:00" },
         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\u6fb3\u5927\u5229\u4e9a\u4e1c\u90e8\u6807\u51c6\u65f6\u95f4",  "+10:00" },
         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\u6089\u5C3C\u65F6\u95F4", "Australia/Sydney" },
         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\u6fb3\u5927\u5229\u4e9a\u4e1c\u90e8\u65f6\u95f4", "Australia/Sydney" },
@@ -1040,12 +1035,10 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH, "+0:00" },
         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
-        { "zh", "Europe/London", "2004-01-15T00:00:00Z", "V", "GMT", "+0:00" },
         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\u683C\u6797\u5C3C\u6CBB\u6807\u51C6\u65F6\u95F4", "+0:00" },
         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"+0100", "+1:00" },
-        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "z", GMT_ZH+"+0100", "+1:00" },
-        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "V", GMT_ZH+"+0100", "+1:00" },
+        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "z", GMT_ZH+"+1", "+1:00" },
         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\u82f1\u56fd\u590f\u4ee4\u65f6\u95f4", "+1:00" },
         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "v", "\u82f1\u56fd\u65f6\u95f4", "Europe/London" },
         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\u82f1\u56fd\u65f6\u95f4", "Europe/London" },
@@ -1053,23 +1046,23 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"-0300", "-3:00" },
-        { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", GMT_ZH+"-0300", "-3:00" },
+        { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", GMT_ZH+"-3", "-3:00" },
         { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", GMT_ZH+"-0300", "-3:00" },
         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"-0300", "-3:00" },
-        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", GMT_ZH+"-0300", "-3:00" },
+        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", GMT_ZH+"-3", "-3:00" },
         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", GMT_ZH+"-0300", "-3:00" },
-        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", GMT_ZH+"-0300", "-3:00" },
+        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", GMT_ZH+"-3", "-3:00" },
         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", GMT_ZH+"-0300", "-3:00" },
 
         // JB#5150
         { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
         { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"+0530", "+5:30" },
-        { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", GMT_ZH+"+0530", "+5:30" },
+        { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", GMT_ZH+"+530", "+5:30" },
         { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\u5370\u5ea6\u65f6\u95f4", "+5:30" },
         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"+0530", "+5:30" },
-        { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", GMT_ZH+"+0530", "+05:30" },
+        { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", GMT_ZH+"+530", "+05:30" },
         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\u5370\u5ea6\u65f6\u95f4", "+5:30" },
         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\u5370\u5ea6\u65f6\u95f4", "Asia/Calcutta" },
         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\u5370\u5EA6\u65f6\u95f4", "Asia/Calcutta" },
@@ -1082,66 +1075,66 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
         { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
-        { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-08:00", "-8:00" },
+        { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
         { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\u092a\u094d\u0930\u0936\u093e\u0902\u0924\u0020\u092e\u093e\u0928\u0915\u0020\u0938\u092e\u092f", "-8:00" },
         { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
         { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
-        { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-07:00", "-7:00" },
+        { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
         { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\u092A\u094D\u0930\u0936\u093E\u0902\u0924 \u0926\u093F\u0935\u093E\u0935\u0932\u094B\u0915 \u0938\u092E\u092F", "-7:00" },
         { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\u0932\u094B\u0938 \u090F\u0902\u091C\u093F\u0932\u0947\u0938 \u0938\u092E\u092F", "America/Los_Angeles" },
         { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\u092A\u094D\u0930\u0936\u093E\u0902\u0924 \u0938\u092E\u092F", "America/Los_Angeles" },
 
         { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u0905\u0930\u094D\u091C\u0947\u0902\u091F\u0940\u0928\u093E \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "-3:00" },
         { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u0905\u0930\u094D\u091C\u0947\u0902\u091F\u0940\u0928\u093E \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "-3:00" },
         { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u092C\u094D\u092F\u0942\u0928\u0938 \u0906\u092F\u0930\u0938 \u0938\u092E\u092F", "America/Buenos_Aires" },
         { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\u0905\u0930\u094D\u091C\u0947\u0902\u091F\u0940\u0928\u093E \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "America/Buenos_Aires" },
 
         { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u0905\u0930\u094D\u091C\u0947\u0902\u091F\u0940\u0928\u093E \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "-3:00" },
         { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u0905\u0930\u094D\u091C\u0947\u0902\u091F\u0940\u0928\u093E \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "-3:00" },
         { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u092C\u094D\u092F\u0942\u0928\u0938 \u0906\u092F\u0930\u0938 \u0938\u092E\u092F", "America/Buenos_Aires" },
         { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\u0905\u0930\u094D\u091C\u0947\u0902\u091F\u0940\u0928\u093E \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "America/Buenos_Aires" },
 
         { "hi", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
         { "hi", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
-        { "hi", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-05:00", "-5:00" },
+        { "hi", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
         { "hi", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\u0915\u094d\u092f\u0942\u092c\u093e \u0915\u093e \u092e\u093e\u0928\u0915 \u0938\u092e\u092f", "-5:00" },
         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
-        { "hi", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-04:00", "-4:00" },
+        { "hi", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\u0915\u094d\u092f\u0942\u092c\u093e \u0915\u093e \u0921\u0947\u0932\u093e\u0907\u091f \u091f\u093e\u0907\u092e", "-4:00" },
         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "v", "\u0915\u094d\u092f\u0942\u092c\u093e \u0938\u092E\u092F", "America/Havana" },
         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\u0915\u094d\u092f\u0942\u092c\u093e \u0915\u093e \u0938\u092E\u092F", "America/Havana" },
 
         { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
         { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
-        { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11:00", "+11:00" },
+        { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
         { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\u0911\u0938\u094D\u200D\u091F\u094D\u0930\u0947\u0932\u093F\u092F\u093E\u0908 \u092A\u0942\u0930\u094D\u0935\u0940 \u0926\u093F\u0935\u093E\u0935\u0932\u094B\u0915 \u0938\u092E\u092F", "+11:00" },
         { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
         { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
-        { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10:00", "+10:00" },
+        { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
         { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\u0911\u0938\u094D\u200D\u091F\u094D\u0930\u0947\u0932\u093F\u092F\u093E\u0908 \u092A\u0942\u0930\u094D\u0935\u0940 \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "+10:00" },
         { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\u0938\u093F\u0921\u0928\u0940 \u0938\u092E\u092F", "Australia/Sydney" },
         { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\u092A\u0942\u0930\u094D\u0935\u0940 \u0911\u0938\u094D\u091F\u094D\u0930\u0947\u0932\u093F\u092F\u093E\u0908 \u0938\u092E\u092F", "Australia/Sydney" },
 
         { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
         { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
-        { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11:00", "+11:00" },
+        { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
         { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\u0911\u0938\u094D\u200D\u091F\u094D\u0930\u0947\u0932\u093F\u092F\u093E\u0908 \u092A\u0942\u0930\u094D\u0935\u0940 \u0926\u093F\u0935\u093E\u0935\u0932\u094B\u0915 \u0938\u092E\u092F", "+11:00" },
         { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
         { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
-        { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10:00", "+10:00" },
+        { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
         { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\u0911\u0938\u094D\u200D\u091F\u094D\u0930\u0947\u0932\u093F\u092F\u093E\u0908 \u092A\u0942\u0930\u094D\u0935\u0940 \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "+10:00" },
         { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\u0938\u093F\u0921\u0928\u0940 \u0938\u092E\u092F", "Australia/Sydney" },
         { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\u092A\u0942\u0930\u094D\u0935\u0940 \u0911\u0938\u094D\u091F\u094D\u0930\u0947\u0932\u093F\u092F\u093E\u0908 \u0938\u092E\u092F", "Australia/Sydney" },
@@ -1152,20 +1145,20 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         { "hi", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\u0917\u094d\u0930\u0940\u0928\u0935\u093f\u091a \u092e\u0940\u0928 \u091f\u093e\u0907\u092e", "+0:00" },
         { "hi", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
         { "hi", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
-        { "hi", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+01:00", "+1:00" },
+        { "hi", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
         { "hi", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "GMT+01:00", "+1:00" },
         { "hi", "Europe/London", "2004-07-15T00:00:00Z", "v", "\u092C\u094D\u0930\u093F\u091F\u0947\u0928 \u0938\u092E\u092F", "Europe/London" },
         { "hi", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\u092C\u094D\u0930\u093F\u091F\u0947\u0928 \u0938\u092E\u092F", "Europe/London" },
 
         { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
-        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-03:00", "-3:00" },
+        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
 
         { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
@@ -1183,13 +1176,11 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
         { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"-0800", "-8:00" },
-        { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", GMT_BG+"-0800", "America/Los_Angeles" },
-        { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "V", GMT_BG+"-0800", "America/Los_Angeles" },
+        { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", GMT_BG+"-8", "America/Los_Angeles" },
         { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\u0422\u0438\u0445\u043E\u043E\u043A\u0435\u0430\u043D\u0441\u043A\u0430 \u0447\u0430\u0441\u043E\u0432\u0430 \u0437\u043E\u043D\u0430", "America/Los_Angeles" },
         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"-0700", "-7:00" },
-        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", GMT_BG+"-0700", "America/Los_Angeles" },
-        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "V", GMT_BG+"-0700", "America/Los_Angeles" },
+        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", GMT_BG+"-7", "America/Los_Angeles" },
         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\u0422\u0438\u0445\u043E\u043E\u043A\u0435\u0430\u043D\u0441\u043A\u0430 \u043B\u044F\u0442\u043D\u0430 \u0447\u0430\u0441\u043E\u0432\u0430 \u0437\u043E\u043D\u0430", "America/Los_Angeles" },
     // icu bg.txt has exemplar city for this time zone
         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\u041B\u043E\u0441 \u0410\u043D\u0436\u0435\u043B\u0438\u0441 \u0432\u0440\u0435\u043C\u0435", "America/Los_Angeles" },
@@ -1198,22 +1189,22 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"-0300", "-3:00" },
-        { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", GMT_BG+"-0300", "-3:00" },
+        { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", GMT_BG+"-3", "-3:00" },
         { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u0410\u0440\u0436\u0435\u043D\u0442\u0438\u043D\u0430 \u2013 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "-3:00" },
         { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"-0300", "-3:00" },
-        { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", GMT_BG+"-0300", "-3:00" },
+        { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", GMT_BG+"-3", "-3:00" },
         { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u0410\u0440\u0436\u0435\u043D\u0442\u0438\u043D\u0430 \u2013 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "-3:00" },
         { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u0411\u0443\u0435\u043D\u043E\u0441 \u0410\u0439\u0440\u0435\u0441 \u0432\u0440\u0435\u043C\u0435", "America/Buenos_Aires" },
         { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\u0410\u0440\u0436\u0435\u043D\u0442\u0438\u043D\u0430 \u2013 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "America/Buenos_Aires" },
 
         { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"-0300", "-3:00" },
-        { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", GMT_BG+"-0300", "-3:00" },
+        { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", GMT_BG+"-3", "-3:00" },
         { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u0410\u0440\u0436\u0435\u043D\u0442\u0438\u043D\u0430 \u2013 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "-3:00" },
         { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"-0300", "-3:00" },
-        { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", GMT_BG+"-0300", "-3:00" },
+        { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", GMT_BG+"-3", "-3:00" },
         { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u0410\u0440\u0436\u0435\u043D\u0442\u0438\u043D\u0430 \u2013 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "-3:00" },
     // icu bg.txt does not have info for this time zone
         { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u0411\u0443\u0435\u043D\u043E\u0441 \u0410\u0439\u0440\u0435\u0441 \u0432\u0440\u0435\u043C\u0435", "America/Buenos_Aires" },
@@ -1221,33 +1212,33 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "bg", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
         { "bg", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"-0500", "-5:00" },
-        { "bg", "America/Havana", "2004-01-15T00:00:00Z", "z", GMT_BG+"-0500", "-5:00" },
+        { "bg", "America/Havana", "2004-01-15T00:00:00Z", "z", GMT_BG+"-5", "-5:00" },
         { "bg", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\u041a\u0443\u0431\u0438\u043d\u0441\u043a\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "-5:00" },
         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"-0400", "-4:00" },
-        { "bg", "America/Havana", "2004-07-15T00:00:00Z", "z", GMT_BG+"-0400", "-4:00" },
+        { "bg", "America/Havana", "2004-07-15T00:00:00Z", "z", GMT_BG+"-4", "-4:00" },
         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\u041a\u0443\u0431\u0438\u043d\u0441\u043a\u043e \u043b\u044f\u0442\u043d\u043e \u0447\u0430\u0441\u043e\u0432\u043e \u0432\u0440\u0435\u043c\u0435", "-4:00" },
         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "v", "\u041a\u0443\u0431\u0430 \u0432\u0440\u0435\u043C\u0435", "America/Havana" },
         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\u041a\u0443\u0431\u0438\u043d\u0441\u043a\u043e \u0432\u0440\u0435\u043C\u0435", "America/Havana" },
 
         { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
         { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"+1100", "+11:00" },
-        { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "z", GMT_BG+"+1100", "+11:00" },
+        { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "z", GMT_BG+"+11", "+11:00" },
         { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\u0410\u0432\u0441\u0442\u0440\u0430\u043B\u0438\u044F \u2013 \u0438\u0437\u0442\u043E\u0447\u043D\u043E \u043B\u044F\u0442\u043D\u043E \u0447\u0430\u0441\u043E\u0432\u043E \u0432\u0440\u0435\u043C\u0435", "+11:00" },
         { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
         { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"+1000", "+10:00" },
-        { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "z", GMT_BG+"+1000", "+10:00" },
+        { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "z", GMT_BG+"+10", "+10:00" },
         { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\u0410\u0432\u0441\u0442\u0440\u0430\u043B\u0438\u044F \u2013 \u0438\u0437\u0442\u043E\u0447\u043D\u043E \u0441\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u043D\u043E \u0432\u0440\u0435\u043C\u0435", "+10:00" },
         { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\u0421\u0438\u0434\u043D\u0438 \u0432\u0440\u0435\u043C\u0435", "Australia/Sydney" },
         { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\u0410\u0432\u0441\u0442\u0440\u0430\u043B\u0438\u044F \u2013 \u0438\u0437\u0442\u043E\u0447\u043D\u043E \u0432\u0440\u0435\u043C\u0435", "Australia/Sydney" },
 
         { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
         { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"+1100", "+11:00" },
-        { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", GMT_BG+"+1100", "+11:00" },
+        { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", GMT_BG+"+11", "+11:00" },
         { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\u0410\u0432\u0441\u0442\u0440\u0430\u043B\u0438\u044F \u2013 \u0438\u0437\u0442\u043E\u0447\u043D\u043E \u043B\u044F\u0442\u043D\u043E \u0447\u0430\u0441\u043E\u0432\u043E \u0432\u0440\u0435\u043C\u0435", "+11:00" },
         { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
         { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"+1000", "+10:00" },
-        { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", GMT_BG+"+1000", "+10:00" },
+        { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", GMT_BG+"+10", "+10:00" },
         { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\u0410\u0432\u0441\u0442\u0440\u0430\u043B\u0438\u044F \u2013 \u0438\u0437\u0442\u043E\u0447\u043D\u043E \u0441\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u043D\u043E \u0432\u0440\u0435\u043C\u0435", "+10:00" },
         { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\u0421\u0438\u0434\u043D\u0438 \u0432\u0440\u0435\u043C\u0435", "Australia/Sydney" },
         { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\u0410\u0432\u0441\u0442\u0440\u0430\u043B\u0438\u044F \u2013 \u0438\u0437\u0442\u043E\u0447\u043D\u043E \u0432\u0440\u0435\u043C\u0435", "Australia/Sydney" },
@@ -1258,30 +1249,30 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         { "bg", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\u0427\u0430\u0441\u043E\u0432\u0430 \u0437\u043E\u043D\u0430 \u0413\u0440\u0438\u043D\u0443\u0438\u0447", "+0:00" },
         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"+0100", "+1:00" },
-        { "bg", "Europe/London", "2004-07-15T00:00:00Z", "z", GMT_BG+"+0100", "+1:00" },
+        { "bg", "Europe/London", "2004-07-15T00:00:00Z", "z", GMT_BG+"+1", "+1:00" },
         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", GMT_BG+"+0100", "+1:00" },
         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "v", "\u041e\u0431\u0435\u0434\u0438\u043d\u0435\u043d\u043e \u043a\u0440\u0430\u043b\u0441\u0442\u0432\u043e \u0432\u0440\u0435\u043C\u0435", "Europe/London" },
         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\u041e\u0431\u0435\u0434\u0438\u043d\u0435\u043d\u043e \u043a\u0440\u0430\u043b\u0441\u0442\u0432\u043e \u0432\u0440\u0435\u043C\u0435", "Europe/London" },
 
         { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"-0300", "-3:00" },
-        { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", GMT_BG+"-0300", "-3:00" },
+        { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", GMT_BG+"-3", "-3:00" },
         { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", GMT_BG+"-0300", "-3:00" },
         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"-0300", "-3:00" },
-        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", GMT_BG+"-0300", "-3:00" },
+        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", GMT_BG+"-3", "-3:00" },
         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", GMT_BG+"-0300", "-3:00" },
-        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", GMT_BG+"-0300", "-3:00" },
+        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", GMT_BG+"-3", "-3:00" },
         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", GMT_BG+"-0300", "-3:00" },
 
         // JB#5150
         { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
         { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"+0530", "+5:30" },
-        { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", GMT_BG+"+0530", "+5:30" },
+        { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", GMT_BG+"+530", "+5:30" },
         { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\u0418\u043d\u0434\u0438\u0439\u0441\u043a\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "+5:30" },
         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"+0530", "+5:30" },
-        { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", GMT_BG+"+0530", "+05:30" },
+        { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", GMT_BG+"+530", "+05:30" },
         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\u0418\u043d\u0434\u0438\u0439\u0441\u043a\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "+5:30" },
         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\u0418\u043D\u0434\u0438\u044F \u0432\u0440\u0435\u043C\u0435", "Asia/Calcutta" },
         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\u0418\u043d\u0434\u0438\u0439\u0441\u043a\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "Asia/Calcutta" },
@@ -1290,13 +1281,11 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
         { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
-        { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-08:00", "America/Los_Angeles" },
-        { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "V", "GMT-08:00", "America/Los_Angeles" },
+        { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
         { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\u30a2\u30e1\u30ea\u30ab\u592a\u5e73\u6d0b\u6a19\u6e96\u6642", "America/Los_Angeles" },
         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
-        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-07:00", "America/Los_Angeles" },
-        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "V", "GMT-07:00", "America/Los_Angeles" },
+        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\u30a2\u30e1\u30ea\u30ab\u592a\u5e73\u6d0b\u590f\u6642\u9593", "America/Los_Angeles" },
     // icu ja.txt has exemplar city for this time zone
         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\u30ED\u30B5\u30F3\u30BC\u30EB\u30B9\u6642\u9593", "America/Los_Angeles" },
@@ -1305,11 +1294,11 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u30A2\u30EB\u30BC\u30F3\u30C1\u30F3\u6A19\u6E96\u6642", "-3:00" },
         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u30A2\u30EB\u30BC\u30F3\u30C1\u30F3\u6A19\u6E96\u6642", "-3:00" },
     // icu ja.txt does not have info for this time zone
         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u30D6\u30A8\u30CE\u30B9\u30A2\u30A4\u30EC\u30B9\u6642\u9593", "America/Buenos_Aires" },
@@ -1317,11 +1306,11 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u30A2\u30EB\u30BC\u30F3\u30C1\u30F3\u6A19\u6E96\u6642", "-3:00" },
         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u30A2\u30EB\u30BC\u30F3\u30C1\u30F3\u6A19\u6E96\u6642", "-3:00" },
     // icu ja.txt does not have info for this time zone
         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u30D6\u30A8\u30CE\u30B9\u30A2\u30A4\u30EC\u30B9\u6642\u9593", "America/Buenos_Aires" },
@@ -1329,22 +1318,22 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "ja", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
         { "ja", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
-        { "ja", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-05:00", "-5:00" },
+        { "ja", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
         { "ja", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\u30AD\u30E5\u30FC\u30D0\u6A19\u6E96\u6642", "-5:00" },
         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
-        { "ja", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-04:00", "-4:00" },
+        { "ja", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\u30AD\u30E5\u30FC\u30D0\u590F\u6642\u9593", "-4:00" },
         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "v", "\u30ad\u30e5\u30fc\u30d0\u6642\u9593", "America/Havana" },
         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\u30ad\u30e5\u30fc\u30d0\u6642\u9593", "America/Havana" },
 
         { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
         { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
-        { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11:00", "+11:00" },
+        { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
         { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2\u6771\u90E8\u590F\u6642\u9593", "+11:00" },
         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
-        { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10:00", "+10:00" },
+        { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2\u6771\u90E8\u6A19\u6E96\u6642", "+10:00" },
     // icu ja.txt does not have info for this time zone
         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\u30B7\u30C9\u30CB\u30FC\u6642\u9593", "Australia/Sydney" },
@@ -1352,11 +1341,11 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
         { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
-        { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11:00", "+11:00" },
+        { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
         { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2\u6771\u90E8\u590F\u6642\u9593", "+11:00" },
         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
-        { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10:00", "+10:00" },
+        { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2\u6771\u90E8\u6A19\u6E96\u6642", "+10:00" },
         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\u30B7\u30C9\u30CB\u30FC\u6642\u9593", "Australia/Sydney" },
         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2\u6771\u90E8\u6642\u9593", "Australia/Sydney" },
@@ -1364,12 +1353,10 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         { "ja", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
         { "ja", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
         { "ja", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
-        { "ja", "Europe/London", "2004-01-15T00:00:00Z", "V", "GMT", "+0:00" },
         { "ja", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\u30B0\u30EA\u30CB\u30C3\u30B8\u6A19\u6E96\u6642", "+0:00" },
         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
-        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+01:00", "+1:00" },
-        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "V", "GMT+01:00", "+1:00" },
+        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\u82f1\u56fd\u590f\u6642\u9593", "+1:00" },
         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "v", "\u30a4\u30ae\u30ea\u30b9\u6642\u9593", "Europe/London" },
         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\u30a4\u30ae\u30ea\u30b9\u6642\u9593", "Europe/London" },
@@ -1377,23 +1364,23 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
-        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-03:00", "-3:00" },
+        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
 
         // JB#5150
         { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
         { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
-        { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+05:30", "+5:30" },
+        { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
         { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\u30A4\u30F3\u30C9\u6642\u9593", "+5:30" },
         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
-        { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+05:30", "+05:30" },
+        { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\u30A4\u30F3\u30C9\u6642\u9593", "+5:30" },
         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\u30A4\u30F3\u30C9\u6642\u9593", "Asia/Calcutta" },
         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\u30A4\u30F3\u30C9\u6642\u9593", "Asia/Calcutta" },
@@ -1405,66 +1392,66 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
         { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
         { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
-        { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-08:00", "-8:00" },
+        { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
         { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "GMT-08:00", "-8:00" },
         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
-        { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-07:00", "-7:00" },
+        { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "GMT-07:00", "-7:00" },
         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles", "America/Los_Angeles" },
         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Los Angeles", "America/Los_Angeles" },
 
         { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
 
         { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
 
         { "ti", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
         { "ti", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
-        { "ti", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-05:00", "-5:00" },
+        { "ti", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
         { "ti", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "GMT-05:00", "-5:00" },
         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
-        { "ti", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-04:00", "-4:00" },
+        { "ti", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "GMT-04:00", "-4:00" },
         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "v", "CU", "America/Havana" },
         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "CU", "America/Havana" },
 
         { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
         { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
-        { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11:00", "+11:00" },
+        { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
         { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
-        { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10:00", "+10:00" },
+        { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
 
         { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
         { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
-        { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11:00", "+11:00" },
+        { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
         { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
-        { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10:00", "+10:00" },
+        { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
@@ -1475,30 +1462,30 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         { "ti", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "GMT", "+0:00" },
         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
-        { "ti", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+01:00", "+1:00" },
+        { "ti", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "GMT+01:00", "+1:00" },
         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "v", "GB", "Europe/London" },
         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "GB", "Europe/London" },
 
         { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
-        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-03:00", "-3:00" },
+        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
-        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-03:00", "-3:00" },
+        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
 
         // JB#5150
         { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
         { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
-        { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+05:30", "+5:30" },
+        { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
         { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
-        { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+05:30", "+05:30" },
+        { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "IN", "Asia/Calcutta" },
         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "IN", "Asia/Calcutta" },
@@ -1516,8 +1503,8 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "CEST", "+2:00"},
         { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
         { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
-        { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "GMT+01:00", "+1:00"},
-        { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "GMT+02:00", "+2:00"},
+        { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "GMT+1", "+1:00"},
+        { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "GMT+2", "+2:00"},
     };
     /**
      * Verify that strings which contain incomplete specifications are parsed
@@ -2954,9 +2941,15 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
             "HH:mm:ss vvvv",    "10:20:30 UT+10:00",    "10:20:30 +1000",
             "HH:mm:ss zzzz",    "10:20:30 UTC",         "10:20:30 +0000",   // standalone "UTC"
             "ZZZZ HH:mm:ss",    "UT 10:20:30",          "10:20:30 +0000",
-            "V HH:mm:ss",       "UT+0130 10:20:30",     "10:20:30 +0130",
-            "V HH:mm:ss",       "UTC+0130 10:20:30",    "10:20:30 +0130",
-            "HH mm Z ss",       "10 20 GMT-1100 30",    "10:20:30 -1100",
+            "z HH:mm:ss",       "UT+0130 10:20:30",     "10:20:30 +0130",
+            "z HH:mm:ss",       "UTC+0130 10:20:30",    "10:20:30 +0130",
+            // Note: GMT-1100 no longer works because of the introduction of the short
+            // localized GMT support. Previous implementation support this level of
+            // leniency (no separator char in localized GMT format), but the new
+            // implementation handles GMT-11 as the legitimate short localized GMT format
+            // and stop at there. Otherwise, roundtrip would be broken.
+            //"HH mm Z ss",       "10 20 GMT-1100 30",      "10:20:30 -1100",
+            "HH mm Z ss",       "10 20 GMT-11 30",      "10:20:30 -1100",
             "HH:mm:ssZZZZZ",    "14:25:45Z",            "14:25:45 +0000",
             "HH:mm:ssZZZZZ",    "15:00:00-08:00",       "15:00:00 -0800",
         };
index e21b6d7df57110042e5c61e87719acebabb3627f..5fd865779cb2e0ba810b0f459f719605a1a2b864 100644 (file)
@@ -449,7 +449,7 @@ public class DateIntervalFormatTest extends com.ibm.icu.dev.test.TestFmwk {
             
             "zh", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "MMMM", "\\u5341\\u4E00\\u6708", // (fixed expected result per ticket 6872<-6626 and others)
             
-            "zh", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "hmz", "2007/11/10 \\u4e0a\\u534810:10 GMT-0800 \\u2013 2007/11/20 \\u4e0a\\u534810:10 GMT-0800", 
+            "zh", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "hmz", "2007/11/10 \\u4e0a\\u534810:10 GMT-8 \\u2013 2007/11/20 \\u4e0a\\u534810:10 GMT-8", 
             
             "zh", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "h", "2007/11/10 \\u4e0a\\u534810\\u65f6 \\u2013 2007/11/20 \\u4e0a\\u534810\\u65f6", 
             
@@ -459,13 +459,13 @@ public class DateIntervalFormatTest extends com.ibm.icu.dev.test.TestFmwk {
             
             "zh", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "hmv", "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4\\u4E0A\\u534810:00\\u81F3\\u4E0B\\u53482:10", 
             
-            "zh", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "hmz", "GMT-0800\\u4e0a\\u534810:00\\u81f3\\u4e0b\\u53482:10", 
+            "zh", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "hmz", "GMT-8\\u4e0a\\u534810:00\\u81f3\\u4e0b\\u53482:10", 
             
             "zh", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "h", "\\u4e0a\\u534810\\u65F6\\u81f3\\u4e0b\\u53482\\u65f6", 
             
             "zh", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "hv", "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4\\u4E0A\\u534810\\u65F6\\u81F3\\u4E0B\\u53482\\u65F6", 
             
-            "zh", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "hz", "GMT-0800\\u4e0a\\u534810\\u65F6\\u81f3\\u4e0b\\u53482\\u65f6", 
+            "zh", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "hz", "GMT-8\\u4e0a\\u534810\\u65F6\\u81f3\\u4e0b\\u53482\\u65f6", 
             
             "zh", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "dMMMM", "1\\u670810\\u65e5", // (fixed expected result per ticket 6872<-6626)
             
@@ -475,7 +475,7 @@ public class DateIntervalFormatTest extends com.ibm.icu.dev.test.TestFmwk {
             
             "zh", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "h", "\\u4e0a\\u534810\\u65f6", 
             
-            "zh", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "hz", "\\u4e0a\\u534810\\u65f6 GMT-0800", 
+            "zh", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "hz", "\\u4e0a\\u534810\\u65f6 GMT-8", 
             
             "zh", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "EEEEdMMMMy", "2007\\u5e741\\u670810\\u65e5\\u661f\\u671f\\u4e09", // (fixed expected result per ticket 6872<-6626)
             
@@ -586,7 +586,7 @@ public class DateIntervalFormatTest extends com.ibm.icu.dev.test.TestFmwk {
             
             "de", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "EEEEdMMM", "Mittwoch, 10. Jan.", 
             
-            "de", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "hmz", "10:00 vorm. - 2:10 nachm. GMT-08:00", 
+            "de", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "hmz", "10:00 vorm. - 2:10 nachm. GMT-8", 
             
             "de", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "h", "10 vorm. - 2 nachm.", 
             
@@ -596,13 +596,13 @@ public class DateIntervalFormatTest extends com.ibm.icu.dev.test.TestFmwk {
             
             "de", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "hmv", "10:00-10:20 vorm. Los Angeles Zeit", 
             
-            "de", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "hmz", "10:00-10:20 vorm. GMT-08:00", 
+            "de", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "hmz", "10:00-10:20 vorm. GMT-8", 
             
             "de", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "h", "10 vorm.", 
             
             "de", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "hv", "10 vorm. Los Angeles Zeit", 
             
-            "de", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "hz", "10 vorm. GMT-08:00", 
+            "de", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "hz", "10 vorm. GMT-8", 
             
             "de", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "EEEEdMMMy", "Mittwoch, 10. Jan. 2007", 
             
@@ -614,15 +614,15 @@ public class DateIntervalFormatTest extends com.ibm.icu.dev.test.TestFmwk {
             
             "de", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "jmv", "10:10 Los Angeles Zeit", 
 
-            "de", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "hmz", "10:10 vorm. GMT-08:00", 
+            "de", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "hmz", "10:10 vorm. GMT-8", 
             
-            "de", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "jmz", "10:10 GMT-08:00", 
+            "de", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "jmz", "10:10 GMT-8", 
 
             "de", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "h", "10 vorm.", 
             
             "de", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "hv", "10 vorm. Los Angeles Zeit", 
             
-            "de", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "hz", "10 vorm. GMT-08:00", 
+            "de", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "hz", "10 vorm. GMT-8", 
         
             // Thai (default calendar buddhist)
 
index 684523bc3a3077cc5487ba0c451d67f8bbccbd65..b82283f890180feb3cd320491350a316b07f8cdf 100644 (file)
@@ -1,6 +1,6 @@
 /*
  ********************************************************************************
- * Copyright (C) 2007-2012, Google, International Business Machines Corporation *
+ * Copyright (C) 2007-2013, Google, International Business Machines Corporation *
  * and others. All Rights Reserved.                                             *
  ********************************************************************************
  */
@@ -9,10 +9,14 @@ package com.ibm.icu.dev.test.format;
 
 import java.text.ParseException;
 import java.text.ParsePosition;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.EnumSet;
+import java.util.List;
 import java.util.Set;
+import java.util.regex.Pattern;
 
+import com.ibm.icu.impl.ZoneMeta;
 import com.ibm.icu.lang.UCharacter;
 import com.ibm.icu.text.SimpleDateFormat;
 import com.ibm.icu.text.TimeZoneFormat;
@@ -34,7 +38,30 @@ public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         new TimeZoneFormatTest().run(args);
     }
 
-    private static final String[] PATTERNS = {"z", "zzzz", "Z", "ZZZZ", "ZZZZZ", "v", "vvvv", "V", "VVVV"};
+    private static final String[] PATTERNS = {
+        "z",
+        "zzzz",
+        "Z",        // equivalent to "xxxx"
+        "ZZZZ",     // equivalent to "OOOO"
+        "v",
+        "vvvv",
+        "O",
+        "OOOO",
+        "X",
+        "XX",
+        "XXX",
+        "XXXX",
+        "XXXXX",
+        "x",
+        "xx",
+        "xxx",
+        "xxxx",
+        "xxxxx",
+        "V",
+        "VV",
+        "VVV",
+        "VVVV"
+    };
     boolean REALLY_VERBOSE_LOG = false;
 
     /*
@@ -124,15 +151,43 @@ public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
                         tz.getOffset(DATES[datidx].getTime(), false, inOffsets);
                         outtz.getOffset(DATES[datidx].getTime(), false, outOffsets);
 
-                        if (PATTERNS[patidx].equals("VVVV")) {
+                        if (PATTERNS[patidx].equals("V")) {
+                            // Short zone ID - should support roundtrip for canonical CLDR IDs
+                            String canonicalID = TimeZone.getCanonicalID(tzids[tzidx]);
+                            if (!outtz.getID().equals(canonicalID)) {
+                                if (outtz.getID().equals("Etc/Unknown")) {
+                                    // Note that some zones like Asia/Riyadh87 does not have
+                                    // short zone ID and "unk" is used as the fallback
+                                    if (REALLY_VERBOSE_LOG) {
+                                        logln("Canonical round trip failed (probably as expected); 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());
+                                }
+                            }
+                        } else if (PATTERNS[patidx].equals("VV")) {
+                            // Zone ID - full roundtrip support
+                            if (!outtz.getID().equals(tzids[tzidx])) {
+                                errln("Zone ID round trip failed; tz=" + tzids[tzidx]
+                                        + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx]
+                                        + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr
+                                        + ", outtz=" + outtz.getID());
+                            }
+                        } else if (PATTERNS[patidx].equals("VVV") || PATTERNS[patidx].equals("VVVV")) {
                             // Location: time zone rule must be preserved except
                             // zones not actually associated with a specific location.
                             String canonicalID = TimeZone.getCanonicalID(tzids[tzidx]);
-                            boolean hasNoLocation = TimeZone.getRegion(tzids[tzidx]).equals("001");
                             if (canonicalID != null && !outtz.getID().equals(canonicalID)) {
                                 // Canonical ID did not match - check the rules
                                 boolean bFailure = false;
                                 if ((tz instanceof BasicTimeZone) && (outtz instanceof BasicTimeZone)) {
+                                    boolean hasNoLocation = TimeZone.getRegion(tzids[tzidx]).equals("001");
                                     bFailure = !hasNoLocation
                                                 && !((BasicTimeZone)outtz).hasEquivalentTransitions(tz, low, high);
                                 }
@@ -149,7 +204,14 @@ public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
                                 }
                             }
                         } else {
-                            boolean isOffsetFormat = (PATTERNS[patidx].charAt(0) == 'Z');
+                            boolean isOffsetFormat = (PATTERNS[patidx].charAt(0) == 'Z'
+                                    || PATTERNS[patidx].charAt(0) == 'O'
+                                    || PATTERNS[patidx].charAt(0) == 'X'
+                                    || PATTERNS[patidx].charAt(0) == 'x');
+                            boolean minutesOffset = false;
+                            if (PATTERNS[patidx].charAt(0) == 'X' || PATTERNS[patidx].charAt(0) == 'x') {
+                                minutesOffset = PATTERNS[patidx].length() <= 3;
+                            }
 
                             if (!isOffsetFormat) {
                                 // Check if localized GMT format is used as a fallback of name styles
@@ -159,14 +221,18 @@ public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
                                         numDigits++;
                                     }
                                 }
-                                isOffsetFormat = (numDigits >= 3);
+                                isOffsetFormat = (numDigits > 0);
                             }
 
                             if (isOffsetFormat || tzstr.equals(localGMTString)) {
-                                // Localized GMT or RFC: total offset (raw + dst) must be preserved.
+                                // Localized GMT or ISO: total offset (raw + dst) must be preserved.
                                 int inOffset = inOffsets[0] + inOffsets[1];
                                 int outOffset = outOffsets[0] + outOffsets[1];
-                                if (inOffset != outOffset) {
+                                int diff = outOffset - inOffset;
+                                if (minutesOffset) {
+                                    diff = (diff / 60000) * 60000;
+                                }
+                                if (diff != 0) {
                                     errln("Offset round trip failed; tz=" + tzids[tzidx]
                                         + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx]
                                         + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr
@@ -216,8 +282,7 @@ public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         if (TEST_ALL || getInclusion() > 5) {
             startYear = 1900;
         } else {
-//            startYear = 1990;
-            startYear = 1900;
+            startYear = 1990;
         }
 
         Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
@@ -229,10 +294,17 @@ public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         cal.set(endYear, Calendar.JANUARY, 1);
         final long END_TIME = cal.getTimeInMillis();
 
-        // Whether each pattern is ambiguous at DST->STD local time overlap
-        final boolean[] AMBIGUOUS_DST_DECESSION = {false, false, false, false, false, true, true, false, true};
-        // Whether each pattern is ambiguous at STD->STD/DST->DST local time overlap
-        final boolean[] AMBIGUOUS_NEGATIVE_SHIFT = {true, true, false, false, false, true, true, true, true};
+        // These patterns are ambiguous at DST->STD local time overlap
+        List<String> AMBIGUOUS_DST_DECESSION = Arrays.asList("v", "vvvv", "V", "VV", "VVV", "VVVV");
+
+        // These patterns are ambiguous at STD->STD/DST->DST local time overlap
+        List<String> AMBIGUOUS_NEGATIVE_SHIFT = Arrays.asList("z", "zzzz", "v", "vvvv", "V", "VV", "VVV", "VVVV");
+
+        // These patterns only support integer minutes offset
+        List<String> MINUTES_OFFSET = Arrays.asList("X", "XX", "XXX", "x", "xx", "xxx");
+
+        // Regex pattern used for filtering zone IDs without exemplar location
+        final Pattern LOC_EXCLUSION_PATTERN = Pattern.compile("Etc/.*|SystemV/.*|.*/Riyadh8[7-9]");
 
         final String BASEPATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS";
 
@@ -259,8 +331,7 @@ public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
             };
         } else {
             LOCALES = new ULocale[] {
-//                new ULocale("en"),
-                new ULocale("el"),
+                new ULocale("en"),
             };
         }
 
@@ -277,9 +348,27 @@ public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
                 logln("    pattern: " + PATTERNS[patidx]);
                 String pattern = BASEPATTERN + " " + PATTERNS[patidx];
                 SimpleDateFormat sdf = new SimpleDateFormat(pattern, LOCALES[locidx]);
+                boolean minutesOffset = MINUTES_OFFSET.contains(PATTERNS[patidx]);
 
                 Set<String> ids = TimeZone.getAvailableIDs(SystemTimeZoneType.CANONICAL, null, null);
                 for (String id : ids) {
+                    if (PATTERNS[patidx].equals("V")) {
+                        // Some zones do not have short ID assigned, such as Asia/Riyadh87.
+                        // The time roundtrip will fail for such zones with pattern "V" (short zone ID).
+                        // This is expected behavior.
+                        String shortZoneID = ZoneMeta.getShortID(id);
+                        if (shortZoneID == null) {
+                            continue;
+                        }
+                    } else if (PATTERNS[patidx].equals("VVV")) {
+                        // Some zones are not associated with any region, such as Etc/GMT+8.
+                        // The time roundtrip will fail for such zones with pattern "VVV" (exemplar location).
+                        // This is expected behavior.
+                        if (id.indexOf('/') < 0 || LOC_EXCLUSION_PATTERN.matcher(id).matches()) {
+                            continue;
+                        }
+                    }
+
                     BasicTimeZone btz = (BasicTimeZone)TimeZone.getTimeZone(id, TimeZone.TIMEZONE_ICU);
                     TimeZone tz = TimeZone.getTimeZone(id);
                     sdf.setTimeZone(tz);
@@ -302,10 +391,12 @@ public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
                                 expectedRoundTrip[0] = true;
                                 testTimes[1] = t + delta;
                                 expectedRoundTrip[1] = isDstDecession ?
-                                        !AMBIGUOUS_DST_DECESSION[patidx] : !AMBIGUOUS_NEGATIVE_SHIFT[patidx];
+                                        !AMBIGUOUS_DST_DECESSION.contains(PATTERNS[patidx]) :
+                                        !AMBIGUOUS_NEGATIVE_SHIFT.contains(PATTERNS[patidx]);
                                 testTimes[2] = t - 1;
                                 expectedRoundTrip[2] = isDstDecession ?
-                                        !AMBIGUOUS_DST_DECESSION[patidx] : !AMBIGUOUS_NEGATIVE_SHIFT[patidx];
+                                        !AMBIGUOUS_DST_DECESSION.contains(PATTERNS[patidx]) :
+                                        !AMBIGUOUS_NEGATIVE_SHIFT.contains(PATTERNS[patidx]);
                                 testTimes[3] = t;
                                 expectedRoundTrip[3] = true;
                                 testLen = 4;
@@ -324,7 +415,10 @@ public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
                             try {
                                 Date parsedDate = sdf.parse(text);
                                 long restime = parsedDate.getTime();
-                                if (restime != testTimes[testidx]) {
+                                long timeDiff = restime - testTimes[testidx];
+                                boolean bTimeMatch = minutesOffset ?
+                                        (timeDiff/60000)*60000 == 0 : timeDiff == 0;
+                                if (!bTimeMatch) {
                                     StringBuffer msg = new StringBuffer();
                                     msg.append("Time round trip failed for ")
                                         .append("tzid=").append(id)
@@ -334,7 +428,7 @@ public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
                                         .append(", gmt=").append(sdfGMT.format(new Date(testTimes[testidx])))
                                         .append(", time=").append(testTimes[testidx])
                                         .append(", restime=").append(restime)
-                                        .append(", diff=").append(restime - testTimes[testidx]);
+                                        .append(", diff=").append(timeDiff);
                                     if (expectedRoundTrip[testidx]) {
                                         errln("FAIL: " + msg.toString());
                                     } else if (REALLY_VERBOSE_LOG) {
@@ -342,7 +436,8 @@ public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
                                     }
                                 }
                             } catch (ParseException pe) {
-                                errln("FAIL: " + pe.getMessage());
+                                errln("FAIL: " + pe.getMessage() + " tzid=" + id + ", locale=" + LOCALES[locidx] +
+                                        ", pattern=" + PATTERNS[patidx] + ", text=" + text);
                             }
                             times[patidx] += System.currentTimeMillis() - timer;
                         }
@@ -375,25 +470,25 @@ public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
     public void TestParse() {
         final Object[][] DATA = {
-        //   text                   inpos       locale      style                   parseAll?   expected            outpos      time type
-            {"Z",                   0,          "en_US",    Style.ISO8601,          false,      "Etc/GMT",          1,          TimeType.UNKNOWN},
-            {"Z",                   0,          "en_US",    Style.SPECIFIC_LONG,    false,      "Etc/GMT",          1,          TimeType.UNKNOWN},
-            {"Zambia time",         0,          "en_US",    Style.ISO8601,          true,       "Etc/GMT",          1,          TimeType.UNKNOWN},
-            {"Zambia time",         0,          "en_US",    Style.GENERIC_LOCATION, false,      "Africa/Lusaka",    11,         TimeType.UNKNOWN},
-            {"Zambia time",         0,          "en_US",    Style.RFC822,           true,       "Africa/Lusaka",    11,         TimeType.UNKNOWN},
-            {"+00:00",              0,          "en_US",    Style.ISO8601,          false,      "Etc/GMT",          6,          TimeType.UNKNOWN},
-            {"-01:30:45",           0,          "en_US",    Style.ISO8601,          false,      "GMT-01:30:45",     9,          TimeType.UNKNOWN},
-            {"-7",                  0,          "en_US",    Style.RFC822,           false,      "GMT-07:00",        2,          TimeType.UNKNOWN},
-            {"-2222",               0,          "en_US",    Style.RFC822,           false,      "GMT-22:22",        5,          TimeType.UNKNOWN},
-            {"-3333",               0,          "en_US",    Style.RFC822,           false,      "GMT-03:33",        4,          TimeType.UNKNOWN},
-            {"XXX+01:30YYY",        3,          "en_US",    Style.LOCALIZED_GMT,    false,      "GMT+01:30",        9,          TimeType.UNKNOWN},
-            {"GMT0",                0,          "en_US",    Style.SPECIFIC_SHORT,   false,      "Etc/GMT",          3,          TimeType.UNKNOWN},
-            {"EST",                 0,          "en_US",    Style.SPECIFIC_SHORT,   false,      "America/New_York", 3,          TimeType.STANDARD},
-            {"ESTx",                0,          "en_US",    Style.SPECIFIC_SHORT,   false,      "America/New_York", 3,          TimeType.STANDARD},
-            {"EDTx",                0,          "en_US",    Style.SPECIFIC_SHORT,   false,      "America/New_York", 3,          TimeType.DAYLIGHT},
-            {"EST",                 0,          "en_US",    Style.SPECIFIC_LONG,    false,      "",                 0,          TimeType.UNKNOWN},
-            {"EST",                 0,          "en_US",    Style.SPECIFIC_LONG,    true,       "America/New_York", 3,          TimeType.STANDARD},
-            {"EST",                 0,          "en_CA",    Style.SPECIFIC_SHORT,   false,      "America/Toronto",  3,          TimeType.STANDARD},
+        //   text                   inpos       locale      style                       parseAll?   expected            outpos      time type
+            {"Z",                   0,          "en_US",    Style.ISO_EXTENDED_FULL,    false,      "Etc/GMT",          1,          TimeType.UNKNOWN},
+            {"Z",                   0,          "en_US",    Style.SPECIFIC_LONG,        false,      "Etc/GMT",          1,          TimeType.UNKNOWN},
+            {"Zambia time",         0,          "en_US",    Style.ISO_EXTENDED_FULL,    true,       "Etc/GMT",          1,          TimeType.UNKNOWN},
+            {"Zambia time",         0,          "en_US",    Style.GENERIC_LOCATION,     false,      "Africa/Lusaka",    11,         TimeType.UNKNOWN},
+            {"Zambia time",         0,          "en_US",    Style.ISO_BASIC_LOCAL_FULL, true,       "Africa/Lusaka",    11,         TimeType.UNKNOWN},
+            {"+00:00",              0,          "en_US",    Style.ISO_EXTENDED_FULL,    false,      "Etc/GMT",          6,          TimeType.UNKNOWN},
+            {"-01:30:45",           0,          "en_US",    Style.ISO_EXTENDED_FULL,    false,      "GMT-01:30:45",     9,          TimeType.UNKNOWN},
+            {"-7",                  0,          "en_US",    Style.ISO_BASIC_LOCAL_FULL, false,      "GMT-07:00",        2,          TimeType.UNKNOWN},
+            {"-2222",               0,          "en_US",    Style.ISO_BASIC_LOCAL_FULL, false,      "GMT-22:22",        5,          TimeType.UNKNOWN},
+            {"-3333",               0,          "en_US",    Style.ISO_BASIC_LOCAL_FULL, false,      "GMT-03:33",        4,          TimeType.UNKNOWN},
+            {"XXX+01:30YYY",        3,          "en_US",    Style.LOCALIZED_GMT,        false,      "GMT+01:30",        9,          TimeType.UNKNOWN},
+            {"GMT0",                0,          "en_US",    Style.SPECIFIC_SHORT,       false,      "Etc/GMT",          3,          TimeType.UNKNOWN},
+            {"EST",                 0,          "en_US",    Style.SPECIFIC_SHORT,       false,      "America/New_York", 3,          TimeType.STANDARD},
+            {"ESTx",                0,          "en_US",    Style.SPECIFIC_SHORT,       false,      "America/New_York", 3,          TimeType.STANDARD},
+            {"EDTx",                0,          "en_US",    Style.SPECIFIC_SHORT,       false,      "America/New_York", 3,          TimeType.DAYLIGHT},
+            {"EST",                 0,          "en_US",    Style.SPECIFIC_LONG,        false,      null,                 0,          TimeType.UNKNOWN},
+            {"EST",                 0,          "en_US",    Style.SPECIFIC_LONG,        true,       "America/New_York", 3,          TimeType.STANDARD},
+            {"EST",                 0,          "en_CA",    Style.SPECIFIC_SHORT,       false,      "America/Toronto",  3,          TimeType.STANDARD},
         };
 
         for (Object[] test : DATA) {
@@ -413,7 +508,7 @@ public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
 
             String errMsg = null;
             if (tz == null) {
-                if (expID.length() != 0) {
+                if (expID != null) {
                     errMsg = "Parse failure - expected: " + expID;
                 }
             } else if (!tz.getID().equals(expID)) {
@@ -429,4 +524,152 @@ public class TimeZoneFormatTest extends com.ibm.icu.dev.test.TestFmwk {
             }
         }
     }
+
+    public void TestISOFormat() {
+        final int[] OFFSET = {
+            0,          // 0
+            999,        // 0.999s
+            -59999,     // -59.999s
+            60000,      // 1m
+            -77777,     // -1m 17.777s
+            1800000,    // 30m
+            -3600000,   // -1h
+            36000000,   // 10h
+            -37800000,  // -10h 30m
+            -37845000,  // -10h 30m 45s
+            108000000,  // 30h
+        };
+        final String[][] ISO_STR = {
+            // 0
+            {
+                "Z", "Z", "Z", "Z", "Z",
+                "+00", "+0000", "+00:00", "+0000", "+00:00",
+                "+0000"
+            },
+            // 999
+            {
+                "Z", "Z", "Z", "Z", "Z",
+                "+00", "+0000", "+00:00", "+0000", "+00:00",
+                "+0000"
+            },
+            // -59999
+            {
+                "Z", "Z", "Z", "-000059", "-00:00:59",
+                "+00", "+0000", "+00:00", "-000059", "-00:00:59",
+                "-000059"
+            },
+            // 60000
+            {
+                "+0001", "+0001", "+00:01", "+0001", "+00:01",
+                "+0001", "+0001", "+00:01", "+0001", "+00:01",
+                "+0001"
+            },
+            // -77777
+            {
+                "-0001", "-0001", "-00:01", "-000117", "-00:01:17",
+                "-0001", "-0001", "-00:01", "-000117", "-00:01:17",
+                "-000117"
+            },
+            // 1800000
+            {
+                "+0030", "+0030", "+00:30", "+0030", "+00:30",
+                "+0030", "+0030", "+00:30", "+0030", "+00:30",
+                "+0030"
+            },
+            // -3600000
+            {
+                "-01", "-0100", "-01:00", "-0100", "-01:00",
+                "-01", "-0100", "-01:00", "-0100", "-01:00",
+                "-0100"
+            },
+            // 36000000
+            {
+                "+10", "+1000", "+10:00", "+1000", "+10:00",
+                "+10", "+1000", "+10:00", "+1000", "+10:00",
+                "+1000"
+            },
+            // -37800000
+            {
+                "-1030", "-1030", "-10:30", "-1030", "-10:30",
+                "-1030", "-1030", "-10:30", "-1030", "-10:30",
+                "-1030"
+            },
+            // -37845000
+            {
+                "-1030", "-1030", "-10:30", "-103045", "-10:30:45",
+                "-1030", "-1030", "-10:30", "-103045", "-10:30:45",
+                "-103045"
+            },
+            // 108000000
+            {
+                null, null, null, null, null,
+                null, null, null, null, null,
+                null
+            }
+        };
+
+        final String[] PATTERN = {
+            "X", "XX", "XXX", "XXXX", "XXXXX", "x", "xx", "xxx", "xxxx", "xxxxx",
+            "Z", // equivalent to "xxxx"
+        };
+
+        final int[] MIN_OFFSET_UNIT = {
+            60000, 60000, 60000, 1000, 1000, 60000, 60000, 60000, 1000, 1000,
+            1000,
+        };
+
+        // Formatting
+        SimpleDateFormat sdf = new SimpleDateFormat();
+        Date d = new Date();
+
+        for (int i = 0; i < OFFSET.length; i++) {
+            SimpleTimeZone tz = new SimpleTimeZone(OFFSET[i], "Zone Offset:" + String.valueOf(OFFSET[i]) + "ms");
+            sdf.setTimeZone(tz);
+            for (int j = 0; j < PATTERN.length; j++) {
+                sdf.applyPattern(PATTERN[j]);
+                try {
+                    String result = sdf.format(d);
+                    if (!result.equals(ISO_STR[i][j])) {
+                        errln("FAIL: pattern=" + PATTERN[j] + ", offset=" + OFFSET[i] + " -> "
+                            + result + " (expected: " + ISO_STR[i][j] + ")");
+                    }
+                } catch (IllegalArgumentException e) {
+                    if (ISO_STR[i][j] != null) {
+                        errln("FAIL: IAE thrown for pattern=" + PATTERN[j] + ", offset=" + OFFSET[i]
+                                + " (expected: " + ISO_STR[i][j] + ")");
+                    }
+                }
+            }
+        }
+
+        // Parsing
+        SimpleTimeZone bogusTZ = new SimpleTimeZone(-1, "Zone Offset: -1ms");
+        for (int i = 0; i < ISO_STR.length; i++) {
+            for (int j = 0; j < ISO_STR[i].length; j++) {
+                if (ISO_STR[i][j] == null) {
+                    continue;
+                }
+                ParsePosition pos = new ParsePosition(0);
+                Calendar outcal = Calendar.getInstance(bogusTZ);
+                sdf.applyPattern(PATTERN[j]);
+
+                sdf.parse(ISO_STR[i][j], outcal, pos);
+
+                if (pos.getIndex() != ISO_STR[i][j].length()) {
+                    errln("FAIL: Failed to parse the entire input string: " + ISO_STR[i][j]);
+                    continue;
+                }
+
+                TimeZone outtz = outcal.getTimeZone();
+                int outOffset = outtz.getRawOffset();
+                int adjustedOffset = OFFSET[i] / MIN_OFFSET_UNIT[j] * MIN_OFFSET_UNIT[j];
+
+                if (outOffset != adjustedOffset) {
+                    errln("FAIL: Incorrect offset:" + outOffset + "ms for input string: " + ISO_STR[i][j]
+                            + " (expected:" + adjustedOffset + "ms)");
+                }
+            }
+        }
+    }
 }
\ No newline at end of file
index 386469cbc7d960255c25f1c504081276e7258652..fb8f58963385d6759c4a99b812e647eefe5287e7 100644 (file)
@@ -1,6 +1,6 @@
 /**
  *******************************************************************************
- * Copyright (C) 2000-2010, International Business Machines Corporation and    *
+ * Copyright (C) 2000-2013, International Business Machines Corporation and    *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  */
@@ -854,25 +854,25 @@ public class TimeZoneRegression extends TestFmwk {
         // Description, Result, Expected Result
         String[] DATA = {
             "getDisplayName(false, SHORT)/std zone",
-            z1.getDisplayName(false, TimeZone.SHORT), "GMT+01:30",
+            z1.getDisplayName(false, TimeZone.SHORT), "GMT+1:30",
             "getDisplayName(false, LONG)/std zone",
             z1.getDisplayName(false, TimeZone.LONG ), "GMT+01:30",
             "getDisplayName(true, SHORT)/std zone",
-            z1.getDisplayName(true, TimeZone.SHORT), "GMT+01:30",
+            z1.getDisplayName(true, TimeZone.SHORT), "GMT+1:30",
             "getDisplayName(true, LONG)/std zone",
             z1.getDisplayName(true, TimeZone.LONG ), "GMT+01:30",
             "getDisplayName(false, SHORT)/dst zone",
-            z2.getDisplayName(false, TimeZone.SHORT), "GMT+01:30",
+            z2.getDisplayName(false, TimeZone.SHORT), "GMT+1:30",
             "getDisplayName(false, LONG)/dst zone",
             z2.getDisplayName(false, TimeZone.LONG ), "GMT+01:30",
             "getDisplayName(true, SHORT)/dst zone",
-            z2.getDisplayName(true, TimeZone.SHORT), "GMT+02:15",
+            z2.getDisplayName(true, TimeZone.SHORT), "GMT+2:15",
             "getDisplayName(true, LONG)/dst zone",
             z2.getDisplayName(true, TimeZone.LONG ), "GMT+02:15",
-            "DateFormat.format(std)/std zone", fmt1.format(std), "GMT+01:30",
-            "DateFormat.format(dst)/std zone", fmt1.format(dst), "GMT+01:30",
-            "DateFormat.format(std)/dst zone", fmt2.format(std), "GMT+01:30",
-            "DateFormat.format(dst)/dst zone", fmt2.format(dst), "GMT+02:15",
+            "DateFormat.format(std)/std zone", fmt1.format(std), "GMT+1:30",
+            "DateFormat.format(dst)/std zone", fmt1.format(dst), "GMT+1:30",
+            "DateFormat.format(std)/dst zone", fmt2.format(std), "GMT+1:30",
+            "DateFormat.format(dst)/dst zone", fmt2.format(dst), "GMT+2:15",
         };
 
         for (int i=0; i<DATA.length; i+=3) {
index e99d83318634051fba813ee95d16fd4497ef313b..3c5c2257bdb42afcceab2be0db4ad938362c81b9 100644 (file)
@@ -1,6 +1,6 @@
 /**
  *******************************************************************************
- * Copyright (C) 2000-2012, International Business Machines Corporation and    *
+ * Copyright (C) 2000-2013, International Business Machines Corporation and    *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  */
@@ -1666,7 +1666,7 @@ public class TimeZoneTest extends TestFmwk
             //  zone id             locale  summer          format      expected display name
             {"Europe/London",       "en",   Boolean.FALSE,  TZSHORT,    "GMT"},
             {"Europe/London",       "en",   Boolean.FALSE,  TZLONG,     "Greenwich Mean Time"},
-            {"Europe/London",       "en",   Boolean.TRUE,   TZSHORT,    "GMT+01:00" /*"BST"*/},
+            {"Europe/London",       "en",   Boolean.TRUE,   TZSHORT,    "GMT+1" /*"BST"*/},
             {"Europe/London",       "en",   Boolean.TRUE,   TZLONG,     "British Summer Time"},
 
             {"America/Anchorage",   "en",   Boolean.FALSE,  TZSHORT,    "AKST"},
@@ -1675,17 +1675,17 @@ public class TimeZoneTest extends TestFmwk
             {"America/Anchorage",   "en",   Boolean.TRUE,   TZLONG,     "Alaska Daylight Time"},
 
             // Southern Hemisphere, all data from meta:Australia_Western
-            {"Australia/Perth",     "en",   Boolean.FALSE,  TZSHORT,    "GMT+08:00"/*"AWST"*/},
+            {"Australia/Perth",     "en",   Boolean.FALSE,  TZSHORT,    "GMT+8"/*"AWST"*/},
             {"Australia/Perth",     "en",   Boolean.FALSE,  TZLONG,     "Australian Western Standard Time"},
             // Note: Perth does not observe DST currently. When display name is missing,
             // the localized GMT format with the current offset is used even daylight name was
             // requested. See #9350.
-            {"Australia/Perth",     "en",   Boolean.TRUE,   TZSHORT,    "GMT+08:00"/*"AWDT"*/},
+            {"Australia/Perth",     "en",   Boolean.TRUE,   TZSHORT,    "GMT+8"/*"AWDT"*/},
             {"Australia/Perth",     "en",   Boolean.TRUE,   TZLONG,     "Australian Western Daylight Time"},
 
-            {"America/Sao_Paulo",   "en",   Boolean.FALSE,  TZSHORT,    "GMT-03:00"/*"BRT"*/},
+            {"America/Sao_Paulo",   "en",   Boolean.FALSE,  TZSHORT,    "GMT-3"/*"BRT"*/},
             {"America/Sao_Paulo",   "en",   Boolean.FALSE,  TZLONG,     "Brasilia Standard Time"},
-            {"America/Sao_Paulo",   "en",   Boolean.TRUE,   TZSHORT,    "GMT-02:00"/*"BRST"*/},
+            {"America/Sao_Paulo",   "en",   Boolean.TRUE,   TZSHORT,    "GMT-2"/*"BRST"*/},
             {"America/Sao_Paulo",   "en",   Boolean.TRUE,   TZLONG,     "Brasilia Summer Time"},
 
             // No Summer Time, but had it before 1983.
@@ -1695,14 +1695,14 @@ public class TimeZoneTest extends TestFmwk
             {"Pacific/Honolulu",    "en",   Boolean.TRUE,   TZLONG,     "Hawaii-Aleutian Daylight Time"},
 
             // Northern, has Summer, not commonly used.
-            {"Europe/Helsinki",     "en",   Boolean.FALSE,  TZSHORT,    "GMT+02:00"/*"EET"*/},
+            {"Europe/Helsinki",     "en",   Boolean.FALSE,  TZSHORT,    "GMT+2"/*"EET"*/},
             {"Europe/Helsinki",     "en",   Boolean.FALSE,  TZLONG,     "Eastern European Standard Time"},
-            {"Europe/Helsinki",     "en",   Boolean.TRUE,   TZSHORT,    "GMT+03:00"/*"EEST"*/},
+            {"Europe/Helsinki",     "en",   Boolean.TRUE,   TZSHORT,    "GMT+3"/*"EEST"*/},
             {"Europe/Helsinki",     "en",   Boolean.TRUE,   TZLONG,     "Eastern European Summer Time"},
 
             // Repeating the test data for DST.  The test data below trigger the problem reported
             // by Ticket#6644
-            {"Europe/London",       "en",   Boolean.TRUE,   TZSHORT,    "GMT+01:00" /*"BST"*/},
+            {"Europe/London",       "en",   Boolean.TRUE,   TZSHORT,    "GMT+1" /*"BST"*/},
             {"Europe/London",       "en",   Boolean.TRUE,   TZLONG,     "British Summer Time"},
         };