views:

844

answers:

6

Hello!

I'm just wondering if there is a way (maybe with REGEX) to validate that an input on a java desktop app is exactly an string formated as: "YYYY-MM-DD".

I've search but with no success.

Thank you

+1  A: 

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.

Greg Bacon
But this validates only the date format not the actual date is valid or not. I like the idea of @Steve B more or if remember correct, there should be a good validation available in commons validation package too.
Teja Kantamneni
Dates are hard. Although you can verify the FORMAT of the input you can't verify the CONTENT with a simple regex. Recommend you use a parser built for the task.
Chris Nava
+2  A: 

Check out this example

Vishal
+5  A: 

You want 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, SimpleDateFormats are both heavyweight and not threadsafe.

Steve B.
don't forget to call `setLenient(false)` if you want the SimpleDateFormat reject invalid dates. Your code will accept "9999-99-00" (would be `Wed Feb 28 00:00:00 CET 10007`)
Carlos Heuberger
Thank you Carlos, I don't even knew that It will recognize inputs like 2009-20-20.Thanks :)
Sheldon
and another point: SimpleDateFormat does not check the format: "2010-1-8", "10-001-002", ... will be accepted
Carlos Heuberger
+2  A: 

Construct a SimpleDateFormat with the mask, and then call: SimpleDateFormat.parse(String s, ParsePosition p)

Keilly
You can just call the 1-argument method `parse(String)` instead of the 2-argument one. _ _ _ And don't forget to call `setLenient(false)` if you want the SimpleDateFormat reject invalid dates.
Carlos Heuberger
A: 

For fine control, consider an InputVerifier using the SimpleDateFormat("YYYY-MM-dd") suggested by Steve B.

trashgod
A: 

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)

Carlos Heuberger