ICU-10336 merge branch into trunk
X-SVN-Rev: 35318
This commit is contained in:
parent
e9bdf144db
commit
b0c6d643db
@ -456,14 +456,21 @@ public abstract class DateFormat extends UFormat {
|
||||
public enum BooleanAttribute {
|
||||
/**
|
||||
* indicates whitespace tolerance. Also included is trailing dot tolerance.
|
||||
* @internal ICU technology preview
|
||||
* @draft ICU 53
|
||||
*/
|
||||
PARSE_ALLOW_WHITESPACE,
|
||||
/**
|
||||
* indicates tolerance of numeric data when String data may be assumed. eg: YEAR_NAME_FIELD
|
||||
* @internal ICU technology preview
|
||||
* indicates tolerance of numeric data when String data may be assumed.
|
||||
* e.g. YEAR_NAME_FIELD
|
||||
* @draft ICU 53
|
||||
*/
|
||||
PARSE_ALLOW_NUMERIC,
|
||||
/**
|
||||
* indicates tolerance of pattern mismatch between input data and specified format pattern.
|
||||
* e.g. accepting "September" for a month pattern of MMM ("Sep")
|
||||
* @draft ICU 53
|
||||
*/
|
||||
PARSE_MULTIPLE_PATTERNS_FOR_MATCH,
|
||||
/**
|
||||
* indicates tolerance of a partial literal match
|
||||
* @draft ICU 53
|
||||
|
@ -28,7 +28,6 @@ import com.ibm.icu.impl.ICUCache;
|
||||
import com.ibm.icu.impl.PatternProps;
|
||||
import com.ibm.icu.impl.SimpleCache;
|
||||
import com.ibm.icu.lang.UCharacter;
|
||||
import com.ibm.icu.text.BreakIterator;
|
||||
import com.ibm.icu.text.TimeZoneFormat.Style;
|
||||
import com.ibm.icu.text.TimeZoneFormat.TimeType;
|
||||
import com.ibm.icu.util.BasicTimeZone;
|
||||
@ -2918,21 +2917,27 @@ public class SimpleDateFormat extends DateFormat {
|
||||
// count >= 3 // i.e., MMM/MMMM or LLL/LLLL
|
||||
// Want to be able to parse both short and long forms.
|
||||
boolean haveMonthPat = (formatData.leapMonthPatterns != null && formatData.leapMonthPatterns.length >= DateFormatSymbols.DT_MONTH_PATTERN_COUNT);
|
||||
// Try count == 4 first:
|
||||
int newStart = (patternCharIndex == 2)?
|
||||
// Try count == 4 first:, unless we're strict
|
||||
int newStart = 0;
|
||||
if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 4) {
|
||||
newStart = (patternCharIndex == 2)?
|
||||
matchString(text, start, Calendar.MONTH, formatData.months,
|
||||
(haveMonthPat)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_FORMAT_WIDE]: null, cal):
|
||||
matchString(text, start, Calendar.MONTH, formatData.standaloneMonths,
|
||||
(haveMonthPat)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_STANDALONE_WIDE]: null, cal);
|
||||
if (newStart > 0) {
|
||||
return newStart;
|
||||
} else { // count == 4 failed, now try count == 3
|
||||
}
|
||||
}
|
||||
// count == 4 failed, now try count == 3
|
||||
if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 3) {
|
||||
return (patternCharIndex == 2)?
|
||||
matchString(text, start, Calendar.MONTH, formatData.shortMonths,
|
||||
(haveMonthPat)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_FORMAT_ABBREV]: null, cal):
|
||||
matchString(text, start, Calendar.MONTH, formatData.standaloneShortMonths,
|
||||
(haveMonthPat)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_STANDALONE_ABBREV]: null, cal);
|
||||
}
|
||||
return newStart;
|
||||
}
|
||||
case 4: // 'k' - HOUR_OF_DAY (1..24)
|
||||
// [We computed 'value' above.]
|
||||
@ -2970,20 +2975,28 @@ public class SimpleDateFormat extends DateFormat {
|
||||
case 9: { // 'E' - DAY_OF_WEEK
|
||||
// Want to be able to parse at least wide, abbrev, short, and narrow forms.
|
||||
int newStart = 0;
|
||||
if ((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.weekdays, null, cal)) > 0) { // try EEEE wide
|
||||
return newStart;
|
||||
}
|
||||
if ((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.shortWeekdays, null, cal)) > 0) { // try EEE abbrev
|
||||
return newStart;
|
||||
}
|
||||
if (formatData.shorterWeekdays != null) {
|
||||
if((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.shorterWeekdays, null, cal)) > 0) { // try EEEEEE short
|
||||
if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 4) {
|
||||
if ((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.weekdays, null, cal)) > 0) { // try EEEE wide
|
||||
return newStart;
|
||||
}
|
||||
}
|
||||
if (formatData.narrowWeekdays != null) {
|
||||
if((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.narrowWeekdays, null, cal)) > 0) { // try EEEEE narrow
|
||||
if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 3) {
|
||||
if ((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.shortWeekdays, null, cal)) > 0) { // try EEE abbrev
|
||||
return newStart;
|
||||
}
|
||||
}
|
||||
if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 6) {
|
||||
if (formatData.shorterWeekdays != null) {
|
||||
if((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.shorterWeekdays, null, cal)) > 0) { // try EEEEEE short
|
||||
return newStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 5) {
|
||||
if (formatData.narrowWeekdays != null) {
|
||||
if((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.narrowWeekdays, null, cal)) > 0) { // try EEEEE narrow
|
||||
return newStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
return newStart;
|
||||
@ -2995,13 +3008,21 @@ public class SimpleDateFormat extends DateFormat {
|
||||
return pos.getIndex();
|
||||
}
|
||||
// Want to be able to parse at least wide, abbrev, short forms.
|
||||
int newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.standaloneWeekdays, null, cal); // try cccc wide
|
||||
if (newStart > 0) {
|
||||
return newStart;
|
||||
} else if ((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.standaloneShortWeekdays, null, cal)) > 0) { // try ccc abbrev
|
||||
return newStart;
|
||||
} else if (formatData.standaloneShorterWeekdays != null) {
|
||||
return matchString(text, start, Calendar.DAY_OF_WEEK, formatData.standaloneShorterWeekdays, null, cal); // try cccccc short
|
||||
int newStart = 0;
|
||||
if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 4) {
|
||||
if ((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.standaloneWeekdays, null, cal)) > 0) { // try cccc wide
|
||||
return newStart;
|
||||
}
|
||||
}
|
||||
if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 3) {
|
||||
if ((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.standaloneShortWeekdays, null, cal)) > 0) { // try ccc abbrev
|
||||
return newStart;
|
||||
}
|
||||
}
|
||||
if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 6) {
|
||||
if (formatData.standaloneShorterWeekdays != null) {
|
||||
return matchString(text, start, Calendar.DAY_OF_WEEK, formatData.standaloneShorterWeekdays, null, cal); // try cccccc short
|
||||
}
|
||||
}
|
||||
return newStart;
|
||||
}
|
||||
@ -3145,14 +3166,18 @@ public class SimpleDateFormat extends DateFormat {
|
||||
// count >= 3 // i.e., QQQ or QQQQ
|
||||
// Want to be able to parse both short and long forms.
|
||||
// Try count == 4 first:
|
||||
int newStart = matchQuarterString(text, start, Calendar.MONTH,
|
||||
formatData.quarters, cal);
|
||||
if (newStart > 0) {
|
||||
return newStart;
|
||||
} else { // count == 4 failed, now try count == 3
|
||||
int newStart = 0;
|
||||
if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 4) {
|
||||
if((newStart = matchQuarterString(text, start, Calendar.MONTH, formatData.quarters, cal)) > 0) {
|
||||
return newStart;
|
||||
}
|
||||
}
|
||||
// count == 4 failed, now try count == 3
|
||||
if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 3) {
|
||||
return matchQuarterString(text, start, Calendar.MONTH,
|
||||
formatData.shortQuarters, cal);
|
||||
}
|
||||
return newStart;
|
||||
}
|
||||
|
||||
case 28: // 'q' - STANDALONE QUARTER
|
||||
@ -3167,14 +3192,18 @@ public class SimpleDateFormat extends DateFormat {
|
||||
// count >= 3 // i.e., qqq or qqqq
|
||||
// Want to be able to parse both short and long forms.
|
||||
// Try count == 4 first:
|
||||
int newStart = matchQuarterString(text, start, Calendar.MONTH,
|
||||
formatData.standaloneQuarters, cal);
|
||||
if (newStart > 0) {
|
||||
return newStart;
|
||||
} else { // count == 4 failed, now try count == 3
|
||||
int newStart = 0;
|
||||
if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 4) {
|
||||
if((newStart = matchQuarterString(text, start, Calendar.MONTH, formatData.standaloneQuarters, cal)) > 0) {
|
||||
return newStart;
|
||||
}
|
||||
}
|
||||
// count == 4 failed, now try count == 3
|
||||
if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 3) {
|
||||
return matchQuarterString(text, start, Calendar.MONTH,
|
||||
formatData.standaloneShortQuarters, cal);
|
||||
}
|
||||
return newStart;
|
||||
}
|
||||
|
||||
default:
|
||||
|
@ -4499,4 +4499,91 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void TestParseMultiPatternMatch() {
|
||||
// For details see http://bugs.icu-project.org/trac/ticket/10336
|
||||
|
||||
class TestMultiPatternMatchItem {
|
||||
public boolean leniency;
|
||||
public String parseString;
|
||||
public String pattern;
|
||||
public String expectedResult; // null indicates expected error
|
||||
// Simple constructor
|
||||
public TestMultiPatternMatchItem(boolean len, String parString, String patt, String expResult) {
|
||||
leniency = len;
|
||||
pattern = patt;
|
||||
parseString = parString;
|
||||
expectedResult = expResult;
|
||||
}
|
||||
};
|
||||
|
||||
final TestMultiPatternMatchItem[] items = {
|
||||
// leniency parse String pattern expected result
|
||||
new TestMultiPatternMatchItem(true, "2013-Sep 13", "yyyy-MMM dd", "2013-Sep 13"),
|
||||
new TestMultiPatternMatchItem(true, "2013-September 14", "yyyy-MMM dd", "2013-Sep 14"),
|
||||
new TestMultiPatternMatchItem(false, "2013-September 15", "yyyy-MMM dd", null),
|
||||
new TestMultiPatternMatchItem(false, "2013-September 16", "yyyy-MMMM dd", "2013-September 16"),
|
||||
new TestMultiPatternMatchItem(true, "2013-Sep 17", "yyyy-LLL dd", "2013-Sep 17"),
|
||||
new TestMultiPatternMatchItem(true, "2013-September 18", "yyyy-LLL dd", "2013-Sep 18"),
|
||||
new TestMultiPatternMatchItem(false, "2013-September 19", "yyyy-LLL dd", null),
|
||||
new TestMultiPatternMatchItem(false, "2013-September 20", "yyyy-LLLL dd", "2013-September 20"),
|
||||
new TestMultiPatternMatchItem(true, "2013 Sat Sep 21", "yyyy EEE MMM dd", "2013 Sat Sep 21"),
|
||||
new TestMultiPatternMatchItem(true, "2013 Sunday Sep 22", "yyyy EEE MMM dd", "2013 Sun Sep 22"),
|
||||
new TestMultiPatternMatchItem(false, "2013 Monday Sep 23", "yyyy EEE MMM dd", null),
|
||||
new TestMultiPatternMatchItem(false, "2013 Tuesday Sep 24", "yyyy EEEE MMM dd", "2013 Tuesday Sep 24"),
|
||||
new TestMultiPatternMatchItem(true, "2013 Wed Sep 25", "yyyy eee MMM dd", "2013 Wed Sep 25"),
|
||||
new TestMultiPatternMatchItem(true, "2013 Thu Sep 26", "yyyy eee MMM dd", "2013 Thu Sep 26"),
|
||||
new TestMultiPatternMatchItem(false, "2013 Friday Sep 27", "yyyy eee MMM dd", null),
|
||||
new TestMultiPatternMatchItem(false, "2013 Saturday Sep 28", "yyyy eeee MMM dd", "2013 Saturday Sep 28"),
|
||||
new TestMultiPatternMatchItem(true, "2013 Sun Sep 29", "yyyy ccc MMM dd", "2013 Sun Sep 29"),
|
||||
new TestMultiPatternMatchItem(true, "2013 Monday Sep 30", "yyyy ccc MMM dd", "2013 Mon Sep 30"),
|
||||
new TestMultiPatternMatchItem(false, "2013 Sunday Oct 13", "yyyy ccc MMM dd", null),
|
||||
new TestMultiPatternMatchItem(false, "2013 Monday Oct 14", "yyyy cccc MMM dd", "2013 Monday Oct 14"),
|
||||
new TestMultiPatternMatchItem(true, "2013 Oct 15 Q4", "yyyy MMM dd QQQ", "2013 Oct 15 Q4"),
|
||||
new TestMultiPatternMatchItem(true, "2013 Oct 16 4th quarter", "yyyy MMM dd QQQ", "2013 Oct 16 Q4"),
|
||||
new TestMultiPatternMatchItem(false, "2013 Oct 17 4th quarter", "yyyy MMM dd QQQ", null),
|
||||
new TestMultiPatternMatchItem(false, "2013 Oct 18 Q4", "yyyy MMM dd QQQ", "2013 Oct 18 Q4"),
|
||||
new TestMultiPatternMatchItem(true, "2013 Oct 19 Q4", "yyyy MMM dd qqqq", "2013 Oct 19 4th quarter"),
|
||||
new TestMultiPatternMatchItem(true, "2013 Oct 20 4th quarter", "yyyy MMM dd qqqq", "2013 Oct 20 4th quarter"),
|
||||
new TestMultiPatternMatchItem(false, "2013 Oct 21 Q4", "yyyy MMM dd qqqq", null),
|
||||
new TestMultiPatternMatchItem(false, "2013 Oct 22 4th quarter", "yyyy MMM dd qqqq", "2013 Oct 22 4th quarter"),
|
||||
};
|
||||
|
||||
StringBuffer result = new StringBuffer();
|
||||
Date d = new Date();
|
||||
GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.US);
|
||||
SimpleDateFormat sdfmt = new SimpleDateFormat();
|
||||
ParsePosition p = new ParsePosition(0);
|
||||
for (TestMultiPatternMatchItem item: items) {
|
||||
cal.clear();
|
||||
sdfmt.setCalendar(cal);
|
||||
sdfmt.applyPattern(item.pattern);
|
||||
sdfmt.setLenient(item.leniency);
|
||||
sdfmt.setBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH, item.leniency);
|
||||
result.setLength(0);
|
||||
p.setIndex(0);
|
||||
p.setErrorIndex(-1);
|
||||
d = sdfmt.parse(item.parseString, p);
|
||||
if(item.expectedResult == null) {
|
||||
if(p.getErrorIndex() != -1)
|
||||
continue;
|
||||
else
|
||||
errln("error: unexpected parse success..."+item.parseString + " w/ lenient="+item.leniency+" should have failed");
|
||||
}
|
||||
if(p.getErrorIndex() != -1) {
|
||||
errln("error: parse error for string " +item.parseString + " -- idx["+p.getIndex()+"] errIdx["+p.getErrorIndex()+"]");
|
||||
continue;
|
||||
}
|
||||
cal.setTime(d);
|
||||
result = sdfmt.format(cal, result, new FieldPosition(0));
|
||||
if(!result.toString().equalsIgnoreCase(item.expectedResult)) {
|
||||
errln("error: unexpected format result. expected - " + item.expectedResult + " but result was - " + result);
|
||||
} else {
|
||||
logln("formatted results match! - " + result.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user