Regex date format validation on Java
Use the following regular expression:
^\d{4}-\d{2}-\d{2}$
as in
if (str.matches("\\d{4}-\\d{2}-\\d{2}")) {
...
}
With the matches
method, the anchors ^
and $
(beginning and end of string, respectively) are present implicitly.
You need more than a regex
, for example "9999-99-00" isn't a valid date. There's a SimpleDateFormat
class that's built to do this. More heavyweight, but more comprehensive.
e.g.
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
boolean isValidDate(string input) {
try {
format.parse(input);
return true;
}
catch(ParseException e){
return false;
}
}
Unfortunately, SimpleDateFormat
is both heavyweight and not thread-safe.
Putting it all together:
-
REGEX
doesn't validate values (like "2010-19-19") -
SimpleDateFormat
does not check format ("2010-1-2", "1-0002-003" are accepted)
it's necessary to use both to validate format and value:
public static boolean isValid(String text) {
if (text == null || !text.matches("\\d{4}-[01]\\d-[0-3]\\d"))
return false;
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
df.setLenient(false);
try {
df.parse(text);
return true;
} catch (ParseException ex) {
return false;
}
}
A ThreadLocal can be used to avoid the creation of a new SimpleDateFormat for each call.
It is needed in a multithread context since the SimpleDateFormat is not thread safe:
private static final ThreadLocal<SimpleDateFormat> format = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
df.setLenient(false);
System.out.println("created");
return df;
}
};
public static boolean isValid(String text) {
if (text == null || !text.matches("\\d{4}-[01]\\d-[0-3]\\d"))
return false;
try {
format.get().parse(text);
return true;
} catch (ParseException ex) {
return false;
}
}
(same can be done for a Matcher, that also is not thread safe)
This will do it regex: "^((19|20)\\d\\d)-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])$"
This will take care of valid formats and valid dates. It will not validate the correct days of the month i.e. leap year.
String regex = "^((19|20)\\d\\d)-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])$";
Assert.assertTrue("Date: matched.", Pattern.matches(regex, "2011-1-1"));
Assert.assertFalse("Date (month): not matched.", Pattern.matches(regex, "2011-13-1"));
Good luck!