Billie
Billie

Reputation: 9146

Java - validate that a given string represents a Date, i.e. "YYYY-MM-DD"?

User gives me a String that should represent expire date with the format of "yyyy-mm-dd".

I want to validate whether it's a date or not, and that's how I do it:

try { 
    DateFormat df = new SimpleDateFormat("yyyy-mm-dd");
    System.out.println("Validating " + date + " as date");
    df.parse(date);
} 
catch (ParseException ex) { 
    // not yyyy-mm-dd date.
    System.out.println(": Bad");
    out.println(date + " cannot be parsed as a date. format: yyyy-mm-dd.");
    return;
}

If user gives me "2014-02-02gy.",

Then it prints: "Validating 2014-02-02gy. as date"

i.e. exception has not been thrown.

Why? and how can I validate a date? Thanks in advance.

EDIT: Used regular expression as one of the comentters suggestion:

if (!date.matches("\\d{4}-\\d{2}-\\d{2}")  {
    out.println("Not a date"); 
}

Upvotes: 2

Views: 5795

Answers (6)

user1073494
user1073494

Reputation:

Since DateFormat strangely matches only the start of the string (seems like a bug for me but it's documented, so well..), I'd explicitly add an end delimiter, like this

    DateFormat df = new SimpleDateFormat("yyyy-mm-dd,");
    String date = "2014-02-02,";
    System.out.println("Validating " + date  + " as date");
    df.parse(date);

Upvotes: 0

ThanksForAllTheFish
ThanksForAllTheFish

Reputation: 7241

If you are not committed to use Java standard libraries, take a look at Joda-Time. The library is much more evolved than standard Java Dates. The piece of code for your case becomes as easy and clean as:

import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
...
try {
  DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
  System.out.println("Validating " + date + " as date");
  formatter.parseDateTime(date);
} catch (IllegalArgumentException e) {
  System.out.println(": Bad");
  System.out.println(date + " cannot be parsed as a date. format: yyyy-mm-dd.");
  return;
}
...

On the other hand, if you have to stick to standard Java, I would go for ns47731's or Chris Gerken's solutions (which are roughly equivalent, my preference for Chris but that is personal taste).

Upvotes: 1

Billie
Billie

Reputation: 9146

I used the following regular expression in order to validate a date:

if(!date.matches("\\d{4}-\\d{2}-\\d{2}")  {
      out.println("Not a date"); 
 }

Thanks for everyone that commented or answered :)

Upvotes: 0

ug_
ug_

Reputation: 11440

From the doc of DateFormat.parse

 * Parses text from the beginning of the given string to produce a date.
 * The method may not use the entire text of the given string.
 * <p>
 * See the {@link #parse(String, ParsePosition)} method for more information
 * on date parsing.
 *
 * @param source A <code>String</code> whose beginning should be parsed.
 * @return A <code>Date</code> parsed from the string.
 * @exception ParseException if the beginning of the specified string
 *            cannot be parsed.

"if the beginning of the specified string cannot be parsed." - it parses from the start until it gets the date it needs. So the gy is removed from the example you showed.

To fix:

String date = "2014-02-02gy";
try { 
    DateFormat df = new SimpleDateFormat("yyyy-mm-dd");
    System.out.println("Validating " + date + " as date");
    Date dateObject = df.parse(date);
    if(!df.format(dateObject).equals(date))
        throw new ParseException(date, 0);
} catch (ParseException ex) { // not yyyy-mm-dd date.
    System.out.println(": Bad");
    System.out.println(date + " cannot be parsed as a date. format: yyyy-mm-dd.");
    return;
}

Upvotes: 3

Chris Gerken
Chris Gerken

Reputation: 16392

You could always reverse the parse with a format to see if what you end up with is what you started with.

DateFormat df = new SimpleDateFormat("yyyy-mm-dd");
String after = df.format(df.parse(date));
if (after.equals(date)) {
    // validated
}       

Upvotes: 5

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279910

Note the javadoc of SimpleDateFormat#parse(string) which says

The method may not use the entire text of the given string.

I don't believe you will be able to validate the characters at the end of your String this way. Note that the date is valid. You just want to check that a String matches a certain pattern.

Upvotes: 1

Related Questions