diff --git a/icu4j/src/com/ibm/icu/dev/test/format/DateFormatTest.java b/icu4j/src/com/ibm/icu/dev/test/format/DateFormatTest.java index 35688041598..f86fa80ebca 100755 --- a/icu4j/src/com/ibm/icu/dev/test/format/DateFormatTest.java +++ b/icu4j/src/com/ibm/icu/dev/test/format/DateFormatTest.java @@ -4,8 +4,8 @@ * others. All Rights Reserved. * ******************************************************************************* * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/test/format/DateFormatTest.java,v $ - * $Date: 2003/01/24 19:56:07 $ - * $Revision: 1.11 $ + * $Date: 2003/03/07 01:05:51 $ + * $Revision: 1.12 $ * ***************************************************************************************** */ @@ -841,42 +841,38 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk { */ public void TestSpaceParsing() { - String PARSE_FAILURE = "parse failure"; String DATA[] = { + "yyyy MM dd", + // pattern, input, expexted output (in quotes) - "MMMM d yy", " 04 05 06", PARSE_FAILURE, // MMMM wants Apr/April - "MMMM d yy", "04 05 06", PARSE_FAILURE, - "MM d yy", " 04 05 06", "\"2006 04 05\"", - "MM d yy", "04 05 06", "\"2006 04 05\"", - "MMMM d yy", " Apr 05 06", "\"2006 04 05\"", - "MMMM d yy", "Apr 05 06", "\"2006 04 05\"", + "MMMM d yy", " 04 05 06", null, // MMMM wants Apr/April + null, "04 05 06", null, + "MM d yy", " 04 05 06", "2006 04 05", + null, "04 05 06", "2006 04 05", + "MMMM d yy", " Apr 05 06", "2006 04 05", + null, "Apr 05 06", "2006 04 05", }; - Locale en = new Locale("en", "", ""); - SimpleDateFormat sdfObj = new SimpleDateFormat("", en); + expectParse(DATA, new Locale("en")); + } - int i; - for (i=0; i " + output); - } else { - errln("FAIL: Parse of \"" + DATA[i+1] + "\" with \"" + - DATA[i] + "\" => " + - output + ", expected " + exp); - } - } + /** + * Test handling of "HHmmss" pattern. + */ + public void TestExactCountFormat() { + String DATA[] = { + "yyyy MM dd HH:mm:ss", + + // pattern, input, expected parse or null if expect parse failure + "HHmmss", "123456", "1970 01 01 12:34:56", + null, "12345", "1970 01 01 12:34:05", + null, "1234", null, + null, "00-05", null, + null, "12-34", null, + null, "00+05", null, + }; + + expectParse(DATA, new Locale("en")); } public void TestCoverage() { @@ -903,4 +899,68 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk { errln("fail, date format symbols not equal"); } } + + /** + * Test parsing. Input is an array that starts with the following + * header: + * + * [0] = pattern string to parse [i+2] with + * + * followed by test cases, each of which is 3 array elements: + * + * [i] = pattern, or null to reuse prior pattern + * [i+1] = input string + * [i+2] = expected parse result (parsed with pattern [0]) + * + * If expect parse failure, then [i+2] should be null. + */ + void expectParse(String[] data, Locale loc) { + Date FAIL = null; + String FAIL_STR = "parse failure"; + int i = 0; + + SimpleDateFormat fmt = new SimpleDateFormat("", loc); + SimpleDateFormat ref = new SimpleDateFormat(data[i++], loc); + SimpleDateFormat gotfmt = new SimpleDateFormat("G yyyy MM dd HH:mm:ss z", loc); + + String currentPat = null; + while (i " + gotstr); + } else { + errln("FAIL: " + input + " x " + + currentPat + " => " + gotstr + ", expected " + + expstr); + } + } + } } diff --git a/icu4j/src/com/ibm/icu/text/DateFormatSymbols.java b/icu4j/src/com/ibm/icu/text/DateFormatSymbols.java index 26fa6a9ebdd..242252e99d5 100755 --- a/icu4j/src/com/ibm/icu/text/DateFormatSymbols.java +++ b/icu4j/src/com/ibm/icu/text/DateFormatSymbols.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/text/DateFormatSymbols.java,v $ - * $Date: 2002/12/18 21:20:52 $ - * $Revision: 1.15 $ + * $Date: 2003/03/07 01:05:48 $ + * $Revision: 1.16 $ * ***************************************************************************************** */ @@ -76,6 +76,11 @@ import java.util.Vector; */ public class DateFormatSymbols implements Serializable, Cloneable { + // TODO make sure local pattern char string is 18 characters long, + // that is, that it encompasses the new 'u' char for + // EXTENDED_YEAR. Two options: 1. Make sure resource data is + // correct; 2. Make code add in 'u' at end if len == 17. + /** * Construct a DateFormatSymbols object by loading format data from * resources for the default locale. @@ -185,7 +190,7 @@ public class DateFormatSymbols implements Serializable, Cloneable { * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. * All locales use the same these unlocalized pattern characters. */ - static final String patternChars = "GyMdkHmsSEDFwWahKz"; + static final String patternChars = "GyMdkHmsSEDFwWahKzu"; /** * Localized date-time pattern characters. For example, a locale may diff --git a/icu4j/src/com/ibm/icu/text/SimpleDateFormat.java b/icu4j/src/com/ibm/icu/text/SimpleDateFormat.java index 2c16ee799ae..537fef1f437 100755 --- a/icu4j/src/com/ibm/icu/text/SimpleDateFormat.java +++ b/icu4j/src/com/ibm/icu/text/SimpleDateFormat.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/text/SimpleDateFormat.java,v $ - * $Date: 2002/12/05 01:22:28 $ - * $Revision: 1.17 $ + * $Date: 2003/03/07 01:05:50 $ + * $Revision: 1.18 $ * ***************************************************************************************** */ @@ -246,6 +246,11 @@ public class SimpleDateFormat extends DateFormat { private static final String GMT_MINUS = "GMT-"; private static final String GMT = "GMT"; + // This prefix is designed to NEVER MATCH real text, in order to + // suppress the parsing of negative numbers. Adjust as needed (if + // this becomes valid Unicode). + private static final String SUPPRESS_NEGATIVE_PREFIX = "\uAB00"; + /** * Cache to hold the DateTimePatterns of a Locale. */ @@ -455,7 +460,8 @@ public class SimpleDateFormat extends DateFormat { Calendar.SECOND, Calendar.MILLISECOND, Calendar.DAY_OF_WEEK, Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK_IN_MONTH, Calendar.WEEK_OF_YEAR, Calendar.WEEK_OF_MONTH, - Calendar.AM_PM, Calendar.HOUR, Calendar.HOUR, Calendar.ZONE_OFFSET + Calendar.AM_PM, Calendar.HOUR, Calendar.HOUR, Calendar.ZONE_OFFSET, + Calendar.EXTENDED_YEAR }; // Map index into pattern character string to DateFormat field number @@ -492,15 +498,10 @@ public class SimpleDateFormat extends DateFormat { int maxIntCount = Integer.MAX_VALUE; String current = ""; - // TEMPORARY HACK TODO fix this - if (ch == 'u') { // 'u' - EXTENDED_YEAR - return zeroPaddingNumber(cal.get(Calendar.EXTENDED_YEAR), - 1, maxIntCount); - } - - if ((patternCharIndex=formatData.patternChars.indexOf(ch)) == -1) + if ((patternCharIndex=formatData.patternChars.indexOf(ch)) == -1) { throw new IllegalArgumentException("Illegal pattern character " + "'" + ch + "'"); + } int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex]; int value = cal.get(field); @@ -609,6 +610,7 @@ public class SimpleDateFormat extends DateFormat { // case 12: // 'w' - WEEK_OF_YEAR // case 13: // 'W' - WEEK_OF_MONTH // case 16: // 'K' - HOUR: 0-based. eg, 11PM + 1 hour =>> 0 AM + // case 18: // 'u' - EXTENDED_YEAR current = zeroPaddingNumber(value, count, maxIntCount); break; } // switch (patternCharIndex) @@ -651,6 +653,7 @@ public class SimpleDateFormat extends DateFormat { char prevCh = 0; int count = 0; int interQuoteCount = 1; // Number of chars between quotes + boolean allowNegative = true; for (int i=0; i= text.length()) return -start; - char c = text.charAt(pos.getIndex()); - if (c != ' ' && c != '\t') break; - pos.setIndex(pos.getIndex()+1); - } - if (obeyCount) { - if ((start+count) > text.length()) { - return -start; - } - number = numberFormat.parse(text.substring(0, start+count), pos); - } else { - number = numberFormat.parse(text, pos); - } - if (number == null) { - return -start; - } - value = number.intValue(); - cal.set(Calendar.EXTENDED_YEAR, value); - return pos.getIndex(); - } - - if ((patternCharIndex=formatData.patternChars.indexOf(ch)) == -1) + if ((patternCharIndex=formatData.patternChars.indexOf(ch)) == -1) { return -start; + } int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex]; @@ -1049,9 +1035,9 @@ public class SimpleDateFormat extends DateFormat { if (obeyCount) { if ((start+count) > text.length()) return -start; - number = numberFormat.parse(text.substring(0, start+count), pos); + number = parseInt(text.substring(0, start+count), pos, allowNegative); } - else number = numberFormat.parse(text, pos); + else number = parseInt(text, pos, allowNegative); if (number == null) return -start; value = number.intValue(); @@ -1257,14 +1243,15 @@ public class SimpleDateFormat extends DateFormat { // case 12: // 'w' - WEEK_OF_YEAR // case 13: // 'W' - WEEK_OF_MONTH // case 16: // 'K' - HOUR: 0-based. eg, 11PM + 1 hour =>> 0 AM + // case 18: // 'u' - EXTENDED_YEAR // Handle "generic" fields if (obeyCount) { if ((start+count) > text.length()) return -start; - number = numberFormat.parse(text.substring(0, start+count), pos); + number = parseInt(text.substring(0, start+count), pos, allowNegative); } - else number = numberFormat.parse(text, pos); + else number = parseInt(text, pos, allowNegative); if (number != null) { cal.set(field, number.intValue()); return pos.getIndex(); @@ -1273,6 +1260,28 @@ public class SimpleDateFormat extends DateFormat { } } + /** + * Parse an integer using fNumberFormat. This method is semantically + * const, but actually may modify fNumberFormat. + */ + private Number parseInt(String text, + ParsePosition pos, + boolean allowNegative) { + String oldPrefix = null; + DecimalFormat df = null; + if (!allowNegative) { + try { + df = (DecimalFormat)numberFormat; + oldPrefix = df.getNegativePrefix(); + df.setNegativePrefix(SUPPRESS_NEGATIVE_PREFIX); + } catch (ClassCastException e1) {} + } + Number number = numberFormat.parse(text, pos); + if (!allowNegative) { + df.setNegativePrefix(oldPrefix); + } + return number; + } /** * Translate a pattern, mapping each character in the from string to the