11

Is there a good, strict date parser for Java? I have access to Joda-Time but I have yet to see this option. I found the "Is there a good date parser for Java" question, and while this is related it is sort of the opposite. Whereas that question was asking for a lenient, more fuzzy-logic and prone to human error parser, I would like a strict parser. For example, with both JodaTime (as far as I can tell) and simpleDateFormat, if you have a format "MM/dd/yyyy":

parse this: 40/40/4353

This becomes a valid date. I want a parser that knows that 40 is an invalid month and date. Surely some implementation of this exists in Java?

MetroidFan2002
  • 29,217
  • 16
  • 62
  • 80
  • Really? The year is certainly valid, but as for the day and moth, it is not. I have to see that. If I remember well the extra months will be added to the year, isn't? – OscarRyz Jan 28 '09 at 21:53
  • Apparently it does this, it just started working. I lack the power to close this question, however. – MetroidFan2002 Jan 28 '09 at 22:03
  • Joda time will be added to Java SE finally. This is featured in the front page ( http://java.sun.com/javase/ ): JSR 310: A New Java Date/Time API. It says it is "..mainly based on the Joda Time API" ( http://today.java.net/pub/a/today/2008/09/18/jsr-310-new-java-date-time-api.html) – OscarRyz Jan 28 '09 at 22:05
  • @Metroid: About closing. I guess marking the answer as accepted will be enough. – OscarRyz Jan 28 '09 at 22:06
  • @Oscar: I simply didn't see the close link until close (1) appeared. My mistake. – MetroidFan2002 Jan 28 '09 at 23:21
  • Re: Joda making into Java SE It sounds like it may not make it into Java 7. https://jsr-310.dev.java.net/servlets/ReadMsg?list=dev&msgNo=1389 – yawmark Jan 29 '09 at 01:09

3 Answers3

21

I don't see that Joda recognizes that as a valid date. Example:

strict = org.joda.time.format.DateTimeFormat.forPattern("MM/dd/yyyy")
try {
    strict.parseDateTime('40/40/4353')
    assert false
} catch (org.joda.time.IllegalFieldValueException e) {
    assert 'Cannot parse "40/40/4353": Value 40 for monthOfYear must be in the range [1,12]' == e.message
}



As best as I can tell, neither does DateFormat with setLenient(false). Example:

try {
    df = new java.text.SimpleDateFormat('MM/dd/yyyy')
    df.setLenient(false)
    df.parse('40/40/4353')
    assert false
} catch (java.text.ParseException e) {
    assert e.message =~ 'Unparseable'
}

Hope this helps!

yawmark
  • 1,934
  • 14
  • 16
  • Which version of JodaTime are you using? – MetroidFan2002 Jan 28 '09 at 21:57
  • 1.6 certainly exhibits this behaviour. – Jon Skeet Jan 28 '09 at 22:00
  • That's really odd. I had a test that was failing, but for some reason it works now and I get that exception you mentioned. Very strange. Joda time it is, then! :) – MetroidFan2002 Jan 28 '09 at 22:03
  • 1
    That's good to know about DateFormat (there's so much there it's hard to find the particular method you're looking for), but I like JodaTime because it doesn't have any synchronization issues with a formatter instance. It's a real gotcha with DateFormat. – MetroidFan2002 Jan 28 '09 at 23:28
11

A good way to do strict validation with DateFormat is re-formatting the parsed date and checking equality to the original string:

String myDateString = "87/88/9999";
Date myDate = dateFormat.parse(myDateString);
if (!myDateString.equals(df.format(myDate))){
  throw new ParseException();
}

Works like a charm.

Rolf
  • 7,098
  • 5
  • 38
  • 55
  • How does it handle if e.g. dates or months are entered without a leading zero which the rendering adds? – Thorbjørn Ravn Andersen Jan 26 '11 at 16:51
  • If the rendering is done by the Formatter (like it should), then there is absolutely no problem. If you create an external rendering formatter, your mileage may vary. – Rolf Jan 31 '11 at 18:51
0

You can use the apache.commons.validator.routines.DateValidator to validate the date,if you do not want to use SimpleDateFormat.

Example :

 public static Date validateDate(String value, String pattern) {
       DateValidator validator = new DateValidator();
       Date date = null;
           if (pattern!=null) {    //Pattern is passed
               date = validator.validate(value, pattern);
           } else {
               date = validator.validate(value);
           }
       return date;
    }

So if a null is returned it means that the date is not valid otherwise it's a valid date.This method is an alternative to using the SimpleDateFormat as you don't have to rely on exception being thrown to identify if it's a valid date or not.

Ananthapadmanabhan
  • 5,706
  • 6
  • 22
  • 39