diff --git a/src/changes/changes.xml b/src/changes/changes.xml index c6032259d..e4841227c 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -22,6 +22,7 @@ + FastDateParser does not set error indication in ParsePosition FastDateParser does not handle excess hours as per SimpleDateFormat FastDateParser error - timezones not handled correctly NumberUtils#createNumber() returns positive BigDecimal when negative Float is expected diff --git a/src/main/java/org/apache/commons/lang3/time/FastDateParser.java b/src/main/java/org/apache/commons/lang3/time/FastDateParser.java index a5f22a27d..f53d7a93a 100644 --- a/src/main/java/org/apache/commons/lang3/time/FastDateParser.java +++ b/src/main/java/org/apache/commons/lang3/time/FastDateParser.java @@ -311,8 +311,17 @@ public class FastDateParser implements DateParser, Serializable { return parse(source, pos); } - /* (non-Javadoc) + /** + * This implementation updates the ParsePosition if the parse succeeeds. + * However, unlike the method {@link java.text.SimpleDateFormat#parse(String, ParsePosition)} + * it is not able to set the error Index - i.e. {@link ParsePosition#getErrorIndex()} - if the parse fails. + *

+ * To determine if the parse has succeeded, the caller must check if the current parse position + * given by {@link ParsePosition#getIndex()} has been updated. If the input buffer has been fully + * parsed, then the index will point to just after the end of the input buffer. + * * @see org.apache.commons.lang3.time.DateParser#parse(java.lang.String, java.text.ParsePosition) + * {@inheritDoc} */ @Override public Date parse(final String source, final ParsePosition pos) { diff --git a/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java b/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java index 31e583fb0..bdf5e27f8 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java @@ -19,6 +19,7 @@ package org.apache.commons.lang3.time; import static org.junit.Assert.*; import java.text.ParseException; +import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Collection; @@ -121,17 +122,33 @@ public class FastDateParserSDFTest { checkParse(input); } + @Test + public void testOriginalPP() throws Exception { + checkParsePosition(input); + } + @Test public void testUpperCase() throws Exception { checkParse(input.toUpperCase(locale)); } + @Test + public void testUpperCasePP() throws Exception { + checkParsePosition(input.toUpperCase(locale)); + } + @Test @Ignore // not currently supported public void testLowerCase() throws Exception { checkParse(input.toLowerCase(locale)); } + @Test + @Ignore // not currently supported + public void testLowerCasePP() throws Exception { + checkParsePosition(input.toLowerCase(locale)); + } + private void checkParse(final String formattedDate) throws ParseException { final SimpleDateFormat sdf = new SimpleDateFormat(format, locale); sdf.setTimeZone(timeZone); @@ -172,4 +189,45 @@ public class FastDateParserSDFTest { assertEquals(locale.toString()+" "+formattedDate + " expected same Exception ", sdfE, fdfE); } } + private void checkParsePosition(final String formattedDate) throws ParseException { + final SimpleDateFormat sdf = new SimpleDateFormat(format, locale); + sdf.setTimeZone(timeZone); + final DateParser fdf = new FastDateParser(format, timeZone, locale); + + ParsePosition sdfP = new ParsePosition(0); + Date expectedTime = sdf.parse(formattedDate, sdfP); + if (valid) { + assertEquals("Expected SDF error index -1 ", -1, sdfP.getErrorIndex()); + final int endIndex = sdfP.getIndex(); + final int length = formattedDate.length(); + if (endIndex != length) { + // Error in test data + throw new RuntimeException("Test data error: expected SDF parse to consume entire string; endindex " + endIndex + " != " + length); + } + } else { + final int errorIndex = sdfP.getErrorIndex(); + if (errorIndex == -1) { + throw new RuntimeException("Test data error: expected SDF parse to fail, but got " + expectedTime); + } + } + + final ParsePosition fdfP = new ParsePosition(0); + Date actualTime = fdf.parse(formattedDate, fdfP); + final int fdferrorIndex = fdfP.getErrorIndex(); + if (valid) { + assertEquals("Expected FDF error index -1 ", -1, fdferrorIndex); + final int endIndex = fdfP.getIndex(); + final int length = formattedDate.length(); + assertEquals("Expected FDF to parse full string " + fdfP, length, endIndex); + assertEquals(locale.toString()+" "+formattedDate +"\n",expectedTime, actualTime); + } else { + final int endIndex = fdfP.getIndex(); + if (endIndex != -0) { + fail("Expected FDF parse to fail, but got " + fdfP); + } + if (fdferrorIndex != -1) { + assertEquals("FDF error index should match SDF index (if it is set)", sdfP.getErrorIndex(), fdferrorIndex); + } + } + } }