1

I am parsing date strings from user input with MM-dd-yyyy HH:mm:ss format, and I found 12-20-2012 10:10:10 abcdexxxx could be pasred as well. How can this happen? Here is my code:

SimpleDateFormat df = new SimpleDateFormat( "MM-dd-yyyy HH:mm:ss" );
String currColValue = "12-20-2012 10:10:10 abcdexxxx";
try{
    d=df.parse( currColValue );
}catch( ParseException e ){
    System.out.println("Error parsing date: "+e.getMessage());
}

But there is no exception, the String value is parsed to be a Date. Why?

laalto
  • 150,114
  • 66
  • 286
  • 303
Bugdaily
  • 177
  • 1
  • 2
  • 10

4 Answers4

12

Per the Javadoc of the parse method:

Parses text from the beginning of the given string to produce a date. The method may not use the entire text of the given string.

(emphases mine).

Contrary to the implication of comments above, this has nothing to do with lenient parsing; rather, it's just that this method is not intended to consume the whole string. If you wish to validate that it consumed the whole string, I suppose you could set up a ParsePosition object and use the two-arg overload, and then examine the ParsePosition afterward to see if it parsed to the end of the string.

ruakh
  • 175,680
  • 26
  • 273
  • 307
3

java.time

I should like to contribute the modern answer. This question was asked just the month before java.time, the modern Java date and time API, came out, which we all should be using now.

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd-yyyy HH:mm:ss");
    String currColValue = "12-20-2012 10:10:10 abcdexxxx";
    try {
        LocalDateTime ldt = LocalDateTime.parse(currColValue, formatter);
        // Do something with ldt
    } catch (DateTimeParseException e) {
        System.out.println("Error parsing date and time: " + e.getMessage());
    }

Output:

Error parsing date and time: Text '12-20-2012 10:10:10 abcdexxxx' could not be parsed, unparsed text found at index 19

Contrary to the old SimpleDateFormat class the parse methods of the modern classes do insist on parsing the entire string (there is a way to parse only part of the string if that is what you require). Also please note the precision and clarity of the exception message. By the way, SimpleDateFormat is not only long outdated, it is also notoriously troublesome. You found just one of many surprising problems it has. I recommend that you no longer use SimpleDateFormat and Date.

Link: Oracle tutorial: Date Time explaining how to use java.time.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • Yes. Now we are using JDK 1.8 and I prefer to using LocalDate/LocalDateTime/DateTimeFormatter... but I could not use this version after it just released. – Bugdaily Jan 15 '19 at 02:42
2

Check SimpleDateFormat.parse(String) doc. It clearly says it.

Parses text from the beginning of the given string to produce a date. The method may not use the entire text of the given string.

http://docs.oracle.com/javase/7/docs/api/java/text/DateFormat.html#parse(java.lang.String)

Vaandu
  • 4,857
  • 12
  • 49
  • 75
1

I want to contibute to the above correct answers with examples, using the method overload

public Date parse(String text, ParsePosition pos);

To parse the exact whole string just create a new ParsePosition object (with index 0, indicating that parse needs to start from begin), pass it to the method, and inspect its index property after parse. Index is where the parse did end. If matches with string length then the string matches exactly form start to end.

Here is a unit test demonstrating it

public class DateParseUnitTest {

    @Test
    public void testParse(){
        Date goodDate = parseExact("2019-11-05");
        Date badDate1 = parseExact("foo 2019-11-05");
        Date badDate2 = parseExact("2019-11-05 foo");

        assert(goodDate != null);
        assert(badDate1 == null);
        assert(badDate2 == null);
    }

    @Nullable
    private Date parseExact(@NonNull String text){
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");

        ParsePosition pos = new ParsePosition(0);
        Date date = formatter.parse(text, pos);
        if (pos.getIndex() != text.length())
            return null;

        return date;
    }
}
Luca Corradi
  • 2,031
  • 1
  • 16
  • 17