8072099: Format "ha" is unable to parse hours 10-12
authornishjain
Tue, 31 May 2016 16:19:32 +0900
changeset 38750 b03431b3516b
parent 38749 90c9aeef923a
child 38751 95fb2dcb4d84
8072099: Format "ha" is unable to parse hours 10-12 Reviewed-by: okutsu, peytoia
jdk/src/java.base/share/classes/java/text/SimpleDateFormat.java
jdk/test/java/text/Format/DateFormat/Bug8072099.java
--- a/jdk/src/java.base/share/classes/java/text/SimpleDateFormat.java	Tue May 31 00:15:04 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/text/SimpleDateFormat.java	Tue May 31 16:19:32 2016 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -1491,22 +1491,18 @@
 
                 if (i < compiledPattern.length) {
                     int nextTag = compiledPattern[i] >>> 8;
-                    if (!(nextTag == TAG_QUOTE_ASCII_CHAR ||
-                          nextTag == TAG_QUOTE_CHARS)) {
-                        obeyCount = true;
-                    }
+                    int nextCount = compiledPattern[i] & 0xff;
+                    obeyCount = shouldObeyCount(nextTag, nextCount);
 
                     if (hasFollowingMinusSign &&
                         (nextTag == TAG_QUOTE_ASCII_CHAR ||
                          nextTag == TAG_QUOTE_CHARS)) {
-                        int c;
-                        if (nextTag == TAG_QUOTE_ASCII_CHAR) {
-                            c = compiledPattern[i] & 0xff;
-                        } else {
-                            c = compiledPattern[i+1];
+
+                        if (nextTag != TAG_QUOTE_ASCII_CHAR) {
+                            nextCount = compiledPattern[i+1];
                         }
 
-                        if (c == minusSign) {
+                        if (nextCount == minusSign) {
                             useFollowingMinusSignAsDelimiter = true;
                         }
                     }
@@ -1549,6 +1545,36 @@
         return parsedDate;
     }
 
+    /* If the next tag/pattern is a <Numeric_Field> then the parser
+     * should consider the count of digits while parsing the contigous digits
+     * for the current tag/pattern
+     */
+    private boolean shouldObeyCount(int tag, int count) {
+        switch (tag) {
+            case PATTERN_MONTH:
+            case PATTERN_MONTH_STANDALONE:
+                return count <= 2;
+            case PATTERN_YEAR:
+            case PATTERN_DAY_OF_MONTH:
+            case PATTERN_HOUR_OF_DAY1:
+            case PATTERN_HOUR_OF_DAY0:
+            case PATTERN_MINUTE:
+            case PATTERN_SECOND:
+            case PATTERN_MILLISECOND:
+            case PATTERN_DAY_OF_YEAR:
+            case PATTERN_DAY_OF_WEEK_IN_MONTH:
+            case PATTERN_WEEK_OF_YEAR:
+            case PATTERN_WEEK_OF_MONTH:
+            case PATTERN_HOUR1:
+            case PATTERN_HOUR0:
+            case PATTERN_WEEK_YEAR:
+            case PATTERN_ISO_DAY_OF_WEEK:
+                return true;
+            default:
+                return false;
+        }
+    }
+
     /**
      * Private code-size reduction function used by subParse.
      * @param text the time text being parsed.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/Bug8072099.java	Tue May 31 16:19:32 2016 +0900
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @bug 8072099
+ * @summary check the date time pattern for <NUMERIC_FIELD> which should
+ * not throw ParseException
+ */
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+public class Bug8072099 {
+
+    private static String[][] shouldPass = {
+        {"ha", "11AM"},
+        {"hma", "33AM"},
+        {"ka", "24AM"},
+        {"yyyMMM", "2016May"},
+        {"yyyyDDEEE", "2016366Sat"},
+        {"ddmyyyyz", "22111980GMT+5:30"}
+    };
+
+    public static void main(String[] args) {
+
+        Locale defaultLocale = Locale.getDefault();
+        try {
+            Locale.setDefault(Locale.US);
+            // check the date time pattern which should pass
+            for (String[] pattern : shouldPass) {
+                SimpleDateFormat dateTimeFormat = new SimpleDateFormat(pattern[0]);
+                parseDateTimeInput(dateTimeFormat, pattern[1]);
+            }
+        } finally {
+            Locale.setDefault(defaultLocale);
+        }
+    }
+
+    private static void parseDateTimeInput(SimpleDateFormat format,
+                                           String inputString) {
+        try {
+            format.parse(inputString);
+        } catch (ParseException ex) {
+            throw new RuntimeException("[FAILED: Unable to parse date time"
+                    + " string " + inputString + "]");
+        }
+    }
+
+}