4

This question is raised by the following code:

DateFormat DF = new SimpleDateFormat("yyyyMMdd");
String dateString = "20110133";
System.out.println(DF.parse(dateString));
// Wed Feb 02 00:00:00 CET 2011

The parse method transformed Jan 33 to Feb 02. Is there a way to throw an Exception if the dateString does not represent a real date?

Just like DateTime.ParseExact in .NET.

Zeemee
  • 10,486
  • 14
  • 51
  • 81
  • Modern comment: I strongly recommend that you do not use `DateFormat`, `SimpleDateFormat` and `Date` any more since those classes are troublesome and long outdated. You have seen just a very slight bit of the trouble with them. Use `LocalDate` and `DateTimeFormatter` from [java.time, the modern Java date and time API (since Java 1.8, out in 2014](https://docs.oracle.com/javase/tutorial/datetime/index.html). – Ole V.V. Nov 23 '22 at 06:09
  • It’s simple when you know it: Use `LocalDate.parse(dateString, DateTimeFormatter.BASIC_ISO_DATE)`. For your string it throws `java.time.format.DateTimeParseException: Text '20110133' could not be parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 33`. If he string is `20110230`, the message will be *Text '20110230' could not be parsed: Invalid date 'FEBRUARY 30'*. Enjoy the precise messages. – Ole V.V. Nov 23 '22 at 06:11

3 Answers3

9

Try doing this

DF.setLenient(false);

javadoc reference

Bala R
  • 107,317
  • 23
  • 199
  • 210
  • 1
    It's not perfect and won't work in all instances, see https://stackoverflow.com/questions/13088140/java-how-to-parse-a-date-strictly – rboy Jul 31 '18 at 19:16
4

You can use the setLenient(boolean) method of the DateFormat class to tell it not to be lenient (i.e. accept and then convert) with dates that aren't valid.

Anthony Grist
  • 38,173
  • 8
  • 62
  • 76
  • 1
    Will not always work, see this https://stackoverflow.com/questions/13088140/java-how-to-parse-a-date-strictly – rboy Jul 31 '18 at 19:17
1

java.time

The accepted answer uses legacy date-time API which was the correct thing to do using the standard library in 2011 when the question was asked. In March 2014, java.time API supplanted the error-prone legacy date-time API. Since then, it has been strongly recommended to use this modern date-time API.

The java.time API is based on ISO 8601 and for basic format i.e. yyyyMMdd, it comes with a predefined formatter, DateTimeFormatter.BASIC_ISO_DATE.

Using this predefined formattter, try to parse your string to a LocalDate and catch the exception, if any, to understand the cause.

Demo using java.time API:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

public class Main {
    public static void main(String[] args) {
        String[] samples = { "20221123", "20110133", "20110131", "20110229", "20110228" };
        for (String dateString : samples) {
            try {
                System.out.println("============================");
                System.out.println(
                        dateString + " parsed to " + LocalDate.parse(dateString, DateTimeFormatter.BASIC_ISO_DATE));
            } catch (DateTimeParseException e) {
                System.err.println(e.getMessage());
            }
        }
    }
}

Output:

============================
20221123 parsed to 2022-11-23
============================
Text '20110133' could not be parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 33
============================
20110131 parsed to 2011-01-31
============================
Text '20110229' could not be parsed: Invalid date 'February 29' as '2011' is not a leap year
============================
20110228 parsed to 2011-02-28

Learn more about the modern Date-Time API from Trail: Date Time.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110