1

I have an incoming string which should be a date in format "yyyyMMdd".(e.g today's Date - 20200507) But sometimes input string can be an invalid format and Date parser should give an exception(parse exception), but it is not except it is returning a date object.

Sample Code in case when string is wrong or alphanumeric like below:

class Demo {
public static void main(String args[]) throws Exception {
    String inputString = "9450524Q";
    SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH);
    System.out.println(formatter.parse(inputString));
}}

Output:

Tue Apr 04 00:00:00 IST 9454
Sidharth
  • 1,402
  • 2
  • 16
  • 37
  • I recommend you don’t use `SimpleDateFormat`. That class is notoriously troublesome and long outdated. Instead use `LocalDate` and `DateTimeFormatter`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. May 07 '20 at 13:25

2 Answers2

3

From the JavaDoc of DateFormat from which SimpleDateFormat directly inherits:

By default, parsing is lenient: If the input is not in the form used by this object's format method but can still be parsed as a date, then the parse succeeds. Clients may insist on strict adherence to the format by calling setLenient(false).

TreffnonX
  • 2,924
  • 15
  • 23
PastorPL
  • 968
  • 3
  • 17
  • 36
1

java.time

I recommend that you use java.time, the modern Java date and time API, for your date work. Advantages in your particular case include that the formatter you need is already built in and it does throw the exception that you ask for.

For demonstration I am using this auxiliary method:

public static void tryToParse(String dateString) {
    try {
        LocalDate date
                = LocalDate.parse(dateString, DateTimeFormatter.BASIC_ISO_DATE);
        System.out.println(dateString + " -> " + date);
    } catch (DateTimeParseException dtpe) {
        System.out.println(dateString + ": " + dtpe.getMessage());
    }
}

Trying it out:

    // Valid date
    tryToParse("20200507");
    // Invalid date value
    tryToParse("20210229");
    // Text after date
    tryToParse("20200623Q");
    // Example from question
    tryToParse("9450524Q");

Output is:

20200507 -> 2020-05-07
20210229: Text '20210229' could not be parsed: Invalid date 'February 29' as '2021' is not a leap year
20200623Q: Text '20200623Q' could not be parsed, unparsed text found at index 8
9450524Q: Text '9450524Q' could not be parsed at index 6

Please also enjoy the precise and helpful exception messages. What happened in the last case was: year 9450 and month 52 were parsed, but since 4Q is not a valid two-digit date, the exception was thrown (before validating whether 52 is a valid month number).

What happened in your code

The SimpleDateFormat class is a notorious troublemaker. You have discovered a central design problem with it, but certainly not the only one. What it did was: It parsed 4-digit year, 9450, and two-digit month, 52. There are 12 months in a year, but a SimpleDateFormat with standard settings doesn’t care. It converts 48 of the months to 4 years and ends up in the 4th month 4 years later. Finally 4 is parsed as day of month. The remainder of the text, the Q, is ignored.

As I see it your example exhibits three flaws of SimpleDateFormat:

  1. With standard settings it is lenient, it accepts an invalid month number.
  2. When asked to parse two digits and finding only one, it settles with that one digit without reporting the error.
  3. In the case of unparseable text after the parsed text it does not report any error either.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161