From 985c05a3efb3fa7b13313ce072264154420988fe Mon Sep 17 00:00:00 2001 From: Rich Gillam <62772518+richgillam@users.noreply.github.com> Date: Fri, 27 Aug 2021 17:03:22 -0700 Subject: [PATCH] ICU-21671 Corrected a bug in SimpleDateFormat.subParse() that was causing us to always parse quarter names that begin with numbers as though the number was the whole quarter name. --- .../com/ibm/icu/text/SimpleDateFormat.java | 28 +++++++++++++------ .../icu/dev/test/format/DateFormatTest.java | 3 +- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/SimpleDateFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/SimpleDateFormat.java index 222e9141c08..910f96afa45 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/SimpleDateFormat.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/SimpleDateFormat.java @@ -3609,8 +3609,8 @@ public class SimpleDateFormat extends DateFormat { return ~start; } case 27: // 'Q' - QUARTER - if (count <= 2 || (number != null && getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_NUMERIC))) { - // i.e., Q or QQ. or lenient & have number + if (count <= 2 && number != null) { + // i.e., Q or QQ. // Don't want to parse the quarter if it is a string // while pattern uses numeric style: Q or QQ. // [We computed 'value' above.] @@ -3634,15 +3634,21 @@ public class SimpleDateFormat extends DateFormat { } // count == 3 failed, now try count == 5 if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 5) { - return matchQuarterString(text, start, Calendar.MONTH, - formatData.narrowQuarters, cal); + if ((newStart = matchQuarterString(text, start, Calendar.MONTH, formatData.narrowQuarters, cal)) > 0) { + return newStart; + } + } + // if numeric parsing is on and we got the numeric value already, return it + if (getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_NUMERIC) && number != null) { + cal.set(Calendar.MONTH, (value - 1) * 3); + return pos.getIndex(); } return newStart; } case 28: // 'q' - STANDALONE QUARTER - if (count <= 2 || (number != null && getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_NUMERIC))) { - // i.e., q or qq. or lenient & have number + if (count <= 2 && number != null) { + // i.e., q or qq. // Don't want to parse the quarter if it is a string // while pattern uses numeric style: q or qq. // [We computed 'value' above.] @@ -3666,8 +3672,14 @@ public class SimpleDateFormat extends DateFormat { } // count == 3 failed, now try count == 5 if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 5) { - return matchQuarterString(text, start, Calendar.MONTH, - formatData.standaloneNarrowQuarters, cal); + if ((newStart = matchQuarterString(text, start, Calendar.MONTH, formatData.standaloneNarrowQuarters, cal)) > 0) { + return newStart; + } + } + // if numeric parsing is on and we got the numeric value already, return it + if (getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_NUMERIC) && number != null) { + cal.set(Calendar.MONTH, (value - 1) * 3); + return pos.getIndex(); } return newStart; } diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateFormatTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateFormatTest.java index 793e87039c7..a11a3ffe9e7 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateFormatTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateFormatTest.java @@ -3172,8 +3172,7 @@ public class DateFormatTest extends TestFmwk { String ES_MX_DATA[] = { "yyyy MM dd", -// Test commented out because of ICU-21671 -// "QQQQ y", "fp", "1970 01 01", "1.er trimestre 1970", "1970 01 01", + "QQQQ y", "fp", "1970 01 01", "1.er trimestre 1970", "1970 01 01", "QQQ y", "fp", "1970 01 01", "T1 1970", "1970 01 01", "QQQQQ y", "fp", "1970 01 01", "1 1970", "1970 01 01", "qqqq", "fp", "1970 01 01", "1.er trimestre", "1970 01 01",