What is the use of "lenient "?

Here lenient is used in Java DateFormat. I checked the doc, but didn't get what it was saying.

Can any body please tell me what is the use of this lenient, with one real time example where we use it?


Solution 1:

The javadoc clearly states:

Specify whether or not date/time parsing is to be lenient. With lenient parsing, the parser may use heuristics to interpret inputs that do not precisely match this object's format. With strict parsing, inputs must match this object's format.

So, if you have a pattern and create a date object that strictly matches your pattern, set lenient to false. Also, DateFormat is lenient, by default.

Basically, DateFormat sets Calendar.setLenient and the Javadoc states:

Specifies whether or not date/time interpretation is to be lenient. With lenient interpretation, a date such as "February 942, 1996" will be treated as being equivalent to the 941st day after February 1, 1996. With strict (non-lenient) interpretation, such dates will cause an exception to be thrown. The default is lenient.

Solution 2:

For example this:

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy");
System.out.println(simpleDateFormat.parse("0"));
simpleDateFormat.setLenient(false);
System.out.println(simpleDateFormat.parse("0"));

results in:

Thu Jan 01 00:00:00 CET 1
Exception in thread "main" java.text.ParseException: Unparseable date: "0"
    at java.text.DateFormat.parse(Unknown Source)
    at net.java.quickcheck.generator.support.X.main(X.java:28)

Solution 3:

My advice is to always turn lenient off. I cannot think of a case where you want lenient on, and this setting should never have been the default for classes like SimpleDateFormat. Lenient processing can interpret garbage as valid time strings and opens up errors that may be difficult to catch in testing. Also, if you are using lenient to tolerate variations in time format you are going to get burned. For example:

System.out.println(new SimpleDateFormat("yyyyMMdd").parse("2010-12-30"));

Yields this (your time zone may vary):

Mon Nov 02 00:00:00 EST 2009

This absurd result appears to be the minus one month ("-1"), second day ("2-") of 2010. The zeroth month is December!

Unfortunately, using setLenient(false) does not lead to strict interpretation of the pattern. SimpleDateFormat will tolerate garbage following the pattern match, as discussed here:

SimpleDateFormat.parse() ignores the number of characters in pattern

Also, it is not strict about the number of pattern characters, such as "d" instead of "dd":

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/d");
sdf.setLenient(false);
System.out.println("For 5:  " + sdf.parse("2010/01/5"));
System.out.println("For 05: " + sdf.parse("2010/01/05"));
System.out.println("For 15: " + sdf.parse("2010/01/15"));

Yields:

For 5:  Tue Jan 05 00:00:00 EST 2010
For 05: Tue Jan 05 00:00:00 EST 2010
For 15: Fri Jan 15 00:00:00 EST 2010

Also with setLenient(false) "2010/01/5" is accepted with the pattern "yyyy/MM/dd". And data disagreement is ignored, like "1999/2011" with the pattern "yyyy/yyyy" (answer is 2011).

Using SimpleDateFormat to validate date/time strings is sadly unreliable. If you follow the link above you will see some solutions, including a stricter version of SimpleDateFormat written by me!

Solution 4:

If date is not lenient it will throw error if you pass out of range date but if is not then it will accept is and fix it . e.g August 61st from comment above will become September 30th. Java doc on how to set it . Default is true.