Java 8 LocalDateTime is parsing invalid date
You just need a strict ResolverStyle
.
Parsing a text string occurs in two phases. Phase 1 is a basic text parse according to the fields added to the builder. Phase 2 resolves the parsed field-value pairs into date and/or time objects. This style is used to control how phase 2, resolving, happens.
Sample code - where withResolverStyle(ResolverStyle.STRICT)
is the important change, along with the use of uuuu
rather than yyyy
(where uuuu
is "year" and "yyyy" is "year of era", and therefore ambiguous):
import java.time.*;
import java.time.format.*;
import java.util.*;
public class Test {
public static void main(String[] args) {
String dateFormat = "HH:mm:ss MM/dd/uuuu";
String dateString = "11:30:59 02/31/2015";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter
.ofPattern(dateFormat, Locale.US)
.withResolverStyle(ResolverStyle.STRICT);
try {
LocalDateTime date = LocalDateTime.parse(dateString, dateTimeFormatter);
System.out.println(date);
} catch (DateTimeParseException e) {
// Throw invalid date message
System.out.println("Exception was thrown");
}
}
}
It is not rounding down. February has never had 31 days, and it is impossible to use a validating date / time object to represent a day that doesn't exist.
As a result, it takes the invalid input and gives you the best approximation to the correct date (the last date of February that year).
SimpleDateFormat
inherits from DateFormat
which has a setLenient(boolean value)
method on it. I would expect that if you called setLenient(true)
prior to parsing, it would probably complain more, as detailed in the javadocs.
The Java 8 DateTimeFormatter uses yyyy to mean YEAR_OF_ERA, and uuuu to mean YEAR. You need to modify your pattern string as follows:
String dateFormat = "HH:mm:ss MM/dd/uuuu";
The DateTimeFormatter defaults to using the SMART resolver style, but you want it to use the STRICT resolver style. Modify your dateTimeFormatter initialization code as follows:
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat, Locale.US)
.withResolverStyle(ResolverStyle.STRICT);