I\'m trying to parse a date String which can have tree different formats. Even though the String should not match the second pattern it somehow does and therefore returns a
java.time is the modern Java date and time API and behaves the way you had expected. So it’s a matter of a simple translation of your code:
private static final DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("dd.MM.yyyy");
private static final DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("dd-MM-yyyy");
private static final DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
public static LocalDate parseDate(String dateString) {
LocalDate parsedDate;
try {
parsedDate = LocalDate.parse(dateString, formatter1);
} catch (DateTimeParseException dtpe1) {
try {
parsedDate = LocalDate.parse(dateString, formatter2);
} catch (DateTimeParseException dtpe2) {
parsedDate = LocalDate.parse(dateString, formatter3);
}
}
return parsedDate;
}
(I put the formatters outside your method so they are not created anew for each call. You can put them inside if you prefer.)
Let’s try it out:
LocalDate date = parseDate("2013-01-31");
System.out.println(date);
Output is:
2013-01-31
For numbers DateTimeFormatter.ofPattern takes the number of pattern letters to be the minimum field width. It furthermore assumes that the day of month is never more than two digits. So when trying the format dd-MM-yyyy it successfully parsed 20 as a day of month and then threw a DateTimeParseException because there wasn’t a hyphen (dash) after 20. Then the method went on to try the next formatter.
The SimpleDateFormat class that you tried to use is notoriously troublesome and fortunately long outdated. You met but one of the many problems with it. Repeating the important sentence from the documentation of how it handles numbers from the answer by Teetoo:
For parsing, the number of pattern letters is ignored unless it's needed to separate two adjacent fields.
So new SimpleDateFormat("dd-MM-yyyy") happily parses 2013 as the day of month, 01 as the month and 31 as the year. Next we should have expected it to throw an exception because there aren’t 2013 days in January year 31. But a SimpleDateFormat with default settings doesn’t do that. It just keeps counting days through the following months and years and ends up at July 5 year 36, five and a half years later, the result you observed.
Oracle tutorial: Date Time explaining how to use java.time.