8000529: Regression: SimpleDateFormat incorrectly parses dates formatted with Z and z pattern letters
authorcoffeys
Thu, 25 Apr 2013 21:12:35 +0100
changeset 17178 bf3ea41ef154
parent 17177 59a964c1d518
child 17179 d9ab271f3e50
8000529: Regression: SimpleDateFormat incorrectly parses dates formatted with Z and z pattern letters Reviewed-by: okutsu
jdk/src/share/classes/java/text/CalendarBuilder.java
jdk/src/share/classes/java/text/SimpleDateFormat.java
jdk/test/java/text/Format/DateFormat/Bug7130335.java
--- a/jdk/src/share/classes/java/text/CalendarBuilder.java	Thu Apr 25 14:23:24 2013 -0400
+++ b/jdk/src/share/classes/java/text/CalendarBuilder.java	Thu Apr 25 21:12:35 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -91,6 +91,15 @@
         return field[index] > UNSET;
     }
 
+    CalendarBuilder clear(int index) {
+        if (index == ISO_DAY_OF_WEEK) {
+            index = DAY_OF_WEEK;
+        }
+        field[index] = UNSET;
+        field[MAX_FIELD + index] = 0;
+        return this;
+    }
+
     Calendar establish(Calendar cal) {
         boolean weekDate = isSet(WEEK_YEAR)
                             && field[WEEK_YEAR] > field[YEAR];
--- a/jdk/src/share/classes/java/text/SimpleDateFormat.java	Thu Apr 25 14:23:24 2013 -0400
+++ b/jdk/src/share/classes/java/text/SimpleDateFormat.java	Thu Apr 25 21:12:35 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1719,7 +1719,7 @@
             // determine the local time. (6645292)
             int dstAmount = (nameIndex >= 3) ? tz.getDSTSavings() : 0;
             if (!(useSameName || (nameIndex >= 3 && dstAmount == 0))) {
-                calb.set(Calendar.DST_OFFSET, dstAmount);
+                calb.clear(Calendar.ZONE_OFFSET).set(Calendar.DST_OFFSET, dstAmount);
             }
             return (start + zoneNames[nameIndex].length());
         }
--- a/jdk/test/java/text/Format/DateFormat/Bug7130335.java	Thu Apr 25 14:23:24 2013 -0400
+++ b/jdk/test/java/text/Format/DateFormat/Bug7130335.java	Thu Apr 25 21:12:35 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,34 +23,47 @@
 
 /**
  * @test
- * @bug 7130335
+ * @bug 7130335 7130335
  * @summary Make sure that round-trip conversion (format/parse) works
- *          with old timestamps in Europe/Moscow.
+ *          with old timestamps in Europe/Moscow and with multiple time zone letters.
  */
 import java.text.*;
 import java.util.*;
+import static java.util.GregorianCalendar.*;
 
 public class Bug7130335 {
     private static final TimeZone MOSCOW = TimeZone.getTimeZone("Europe/Moscow");
+    private static final TimeZone LONDON = TimeZone.getTimeZone("Europe/London");
+    private static final TimeZone LA = TimeZone.getTimeZone("America/Los_Angeles");
+    private static final TimeZone[] ZONES = {
+        MOSCOW, LONDON, LA
+    };
 
     public static void main(String[] args) throws Exception {
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z", Locale.US);
         sdf.setTimeZone(MOSCOW);
-        Calendar cal = new GregorianCalendar(MOSCOW);
+        Calendar cal = new GregorianCalendar(MOSCOW, Locale.US);
         cal.clear();
         // Try both +03:00 and +02:00
-        cal.set(1922, Calendar.SEPTEMBER, 30);
+        cal.set(1922, SEPTEMBER, 30);
         test(sdf, cal);
-        cal.add(Calendar.DAY_OF_YEAR, 1);
+        cal.add(DAY_OF_YEAR, 1);
         test(sdf, cal);
-        cal.set(1991, Calendar.MARCH, 31);
+        cal.set(1991, MARCH, 31);
         // in daylight saving time
         test(sdf, cal);
-        cal.add(Calendar.DAY_OF_YEAR, 1);
+        cal.add(DAY_OF_YEAR, 1);
         test(sdf, cal);
         // Try the current timestamp
         cal.setTimeInMillis(System.currentTimeMillis());
         test(sdf, cal);
+
+        // tests for multiple time zone letters (8000529)
+        test8000529("yyyy-MM-dd HH:mm:ss.SSS Z (z)");
+        test8000529("yyyy-MM-dd HH:mm:ss.SSS Z (zzzz)");
+        test8000529("yyyy-MM-dd HH:mm:ss.SSS z (Z)");
+        test8000529("yyyy-MM-dd HH:mm:ss.SSS zzzz (Z)");
+
     }
 
     private static void test(SimpleDateFormat sdf, Calendar cal) throws Exception {
@@ -63,4 +76,19 @@
             throw new RuntimeException("format: " + f + ", parse: " + p);
         }
     }
+
+    private static void test8000529(String fmt) throws Exception {
+        for (TimeZone tz : ZONES) {
+            SimpleDateFormat sdf = new SimpleDateFormat(fmt, Locale.US);
+            sdf.setTimeZone(tz);
+            Calendar cal = new GregorianCalendar(tz, Locale.US);
+            cal.clear();
+            cal.set(2012, JUNE, 22);
+            test(sdf, cal);
+            cal.set(2012, DECEMBER, 22);
+            test(sdf, cal);
+            cal.setTimeInMillis(System.currentTimeMillis());
+            test(sdf, cal);
+        }
+    }
 }