Well, SimpleDateFormat
is known to be a problematic and bugged class, with lots of strange behaviours.
What's probably happening is something similar to the issue described in this article. Considering your pattern and the input:
MM-dd-yyyy
2013-12-28
It's probably reading the month as "20", day as "3" and year as "-28"? (or some other value because I'm not sure how it interprets 2-28
as a 4-digit number). And the final result of this mess is a completely wrong, bizarre date - and don't ask me how it gets to the final result, it's a mistery to me.
Anyway, that can happen when the pattern doesn't match the input format, and the actual values that SimpleDateFormat
reads will be something not so predictable and somewhat counter-intuitive. But what really matters is the fact that this class has lots of issues and design flaws, and it's lenient by default, so it tries to be "smart" and does lots of strange things before giving an error.
If you want to validate the input, just turn off the lenient mode, by calling f.setLenient(false)
as Andreas suggested. This will throw an exception when the input doesn't match the pattern.
But if you're using Java 8, then you should use the java.time API, which is far superior and it solves lots of problems that SimpleDateFormat
has.
To check if a string contains a date in a specific format, use a java.time.format.DateTimeFormatter
. This class is not lenient by default as SimpleDateFormat
, so it should work as expected:
// use the format "month-day-year"
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MM-dd-yyyy");
// try to parse a string in a different format (year-month-day)
LocalDate dt = LocalDate.parse("2013-12-28", fmt); // exception
The code above tries to create a LocalDate
, a class that represents a date (only day, month and year). But if you want to just validate the input (without assigning it to any variable), you can just use the formatter:
fmt.parse("2013-12-28"); // exception