0

I have found nice function which is validating the format and correctness of date String. I wanted to upgrade it to validate only >= 1900 years.

So this is what I found:

public boolean isDateValid(String date) {
    try {
        DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
        df.setLenient(false);
        df.parse(date);
        return true;
    } catch (ParseException e) {
        return false;
    }
}

And this is my upgraded version:

public boolean isDateValid(String date) {
    try {
        DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
        df.setLenient(false);
        df.parse(date);
        Integer year = Integer.parseInt(date.substring(6, 10));
        if (year>= 1900)
            return true;
        else
            return false;
    } catch (ParseException e) {
        return false;
    }
}

So instead of returning true I am checking if the year variable is greater or equal to 1900. The problem is when I run this function with "12-12-1xxx" (edit: or "12-12-1abc"). NumberFormatException is thrown while parsing year String to int. It definitely should not happen because ParseException should be thrown first, breaking the try {} block.

It looks like validation from first listing does not work properly because it accepts every "yyyy" part which begins with a number. Yet everything works fine for "12-12-xxxx" (edit: or "12-12-abcd").

EDIT:

Stop voting down my question and focus while you are reading. The question is very clear: why new SimpleDateFormat("dd-MM-yyyy").parse("12-12-1xxx") does not throw a ParseException?

10
  • 1
    it's working fine on my system , check your input and use latest JDK Commented Sep 23, 2016 at 9:51
  • i can post a snapshot (only as an answer) but it'll make no sense so check for any invalid input Commented Sep 23, 2016 at 9:56
  • yes it is working on my system too. Commented Sep 23, 2016 at 9:58
  • 2
    The problem here is the DateFormat.parse() method. "The method may not use the entire text of the given string." as it is stated in the JavaDoc. Commented Sep 23, 2016 at 10:09
  • 1
    @Am_I_Helpful Slow down, my friend. The question is very clear: Why new SimpleDateFormat("dd-MM-yyyy").parse("12-12-1xxx") does not throw a ParseException? Commented Sep 23, 2016 at 10:09

4 Answers 4

2

As I understand from javadoc the SimpleDateFormat will take 1 as valid part of the year and will parse it. Instead you can try to validate date with regular expressions. You can find some examples here Regex to validate date format dd/mm/yyyy

Sign up to request clarification or add additional context in comments.

1 Comment

And finally we have someone who can read. Thanks for a solution!
1

The documentation of the parse method is:

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.

Because the whole string does not need to be used, then "12-12-1xxx" is actually parsed as "12-12-1", and you get a year 1 date.

Instead of using the substring, you could use the result of the parse method to get the year. getYear is depreciated and returns an offset from 1900 so you might want to convert to a Calendar or LocalDate first.

public boolean isDateValid(String date) {
    try {
        DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
        df.setLenient(false);
        Date parsed = df.parse(date);
        int year = parsed.getYear() + 1900;
        if (year >= 1900)
            return true;
        else
            return false;
    } catch (ParseException e) {
        return false;
    }
}

1 Comment

Thanks for explaining why "parse" method do not throw exception. I think I will catch NumberFormatException in addition. Anyway, thanks for your proposition.
0

I have check your function, and find below details.

If you will pass 12-12-1xxx in main function then also you will get true it will not return false even when I print the date output which is converted by df.parse(date) is Oct 10 00:00:00 GMT 2.

So you will not get parse exception anytime for this,

Suggestion

Either you change ParseException by Exception or also use catch for NumberFormatException as below.

 public boolean isDateValid(String date) {
    try {
        DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
        df.setLenient(false);
        df.parse(date);
        Integer year = Integer.parseInt(date.substring(6, 10));
        if (year>= 1900)
            return true;
        else
            return false;
    } catch (Exception e) { // Use Exception or if you want ParseException then use below commented code
        return false;
    }
    /*catch (NumberFormatException nfe) { // Use this if you use ParseException
        return false;
    }*/
 }

4 Comments

This does not explain why a ParseException is not thrown when an invalid input is entered. Moreover: Catching Exception is a bad practice, because it includes whatever RuntimeExceptions may arise.
check this one docs.oracle.com/javase/7/docs/api/java/text/… you will get idea why you are not getting error as it will consider this kind of text in date according to their criteria
@LittleSanti this is not invalid input and therefor I have show output of that parsed date also, as java doc considering it as date check above link
@Vickyexpert ok, so "12-12-1xxx" or "12-12-1abc" is treated as valid format - but you did not explain why. Catching NumberFormatException can be good solution, I also thought about it. Thanks for advices!
0

If anybody is interested in how the code should look like, here it is:

public boolean isDateValid(String date, String format) {
    if (date.length()!=format.length())
        return false;
    try {
        DateFormat df = new SimpleDateFormat(format);
        df.setLenient(false);

        df.parse(date); // exception is not thrown if day and month is
                        // correct AND the first char of year is a digit

        // so if we have correct day and correct month
        // and we know the year has 4 chars we can try to parse it
        Integer year = Integer.parseInt(date.substring(6, 10));

        if (year>= 1900 && year<=2015) // here we know that the year is 4 digit integer
            return true;               // and we can limit it
        else
            return false;

    } catch (ParseException e) {
        return false;
    } catch (NumberFormatException e) {
        return false;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.