All of us have come among situations when we have to parse user input for validation. Other fields such as text or numeric are rather easy, but Java date validation is little bit difficult and a small error can leave the application in unstable state.
1. Java Date Validation with SimpleDateFormat.parse() method
Usually, SimpleDateFormat.parse() method is used for validation. If parse()
method is able to parse the date, then it is considered that input is valid. Well, it might be incorrect. See below a use case.
package com.howtodoinjava.dateTest; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class TestSetLenient { private static final String DATE_PATTERN = "MM/dd/yyyy"; public static void main(String[] args) { SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN); try { // Lenient conversion result in unexpected output Date d = sdf.parse("2012/12/17"); System.out.println(d); } catch (ParseException e) { e.printStackTrace(); } } } //Output in console : Wed Aug 12 00:00:00 GMT+05:30 184
1.1. What went wrong?
Above date validation is strange for two reasons. First, it should have flagged the validation error, and second the date object obtained is completely useless. So, what went wrong here.
Well, error is in parsing logic. parse(
) method uses positions of pattern keywords in DATE_PATTERN and uses it to parse input string. It is not intelligent by default to use the right characters for parsing and it uses what comes on its way (even slashes).
2. Correct way to validate date in Java – SimpleDateFormat.setLenient()
The solution is to use SimpleDateFormat.setLenient() method to bring the missing intelligence. Look at the strict date validation example given below:
package com.howtodoinjava.dateTest; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class TestSetLenient { private static final String DATE_PATTERN = "MM/dd/yyyy"; public static void main(String[] args) { SimpleDateFormat sdf = new SimpleDateFormat(); sdf.applyPattern(DATE_PATTERN); try { //Lenient conversion result in unexpected output Date d = sdf.parse("2012/12/17"); System.out.println(d); } catch(ParseException e) { e.printStackTrace(); } try { /** * Make is strict validation [SHOULD THROW ERROR] * */ sdf.setLenient(false); //Strict conversion validates the date correctly Date d1 = sdf.parse("2012/12/17"); System.out.println(d1); } catch(ParseException e) { e.printStackTrace(); } try { /** * Make is strict validation [SHOULD PASS] * */ sdf.setLenient(false); //Strict conversion validates the date correctly Date d1 = sdf.parse("12/17/2012"); System.out.println(d1); } catch(ParseException e) { e.printStackTrace(); } } }
Program output.
//Wed Aug 12 00:00:00 GMT+05:30 184 //java.text.ParseException: Unparseable date: "2012/12/17" // at java.text.DateFormat.parse(DateFormat.java:337) // at com.howtodoinjava.dateTest.TestSetLenient.main(TestSetLenient.java:33) //Mon Dec 17 00:00:00 GMT+05:30 2012
So, clearly setting setLenient(false); corrects the parsing behavior of SimpleDateFormat
.
3. Update – Default leniency behavior in date parsing
Source – http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Calendar.html
Calendar
class has two modes for interpreting the calendar fields, lenient and non-lenient. When a calendar is in lenient mode, it accepts a wider range of calendar field values than it produces. When a calendar recomputes field values for return by get()
, all of the calendar fields are normalized.
For example, a lenient GregorianCalendar
interprets “MONTH = JANUARY and DAY_OF_MONTH = 32” as February 1, which is incorrect.
When a Calendar is in non-lenient mode, it throws an exception if there is any inconsistency in its calendar fields. For example, a GregorianCalendar
always produces DAY_OF_MONTH
values between 1 and the length of the month. A non-lenient GregorianCalendar
throws an exception upon calculating its time or calendar field values if any out-of-range field value has been set.
Default is lenient mode.
In this Java date validation example, we learned how to convert string to a particular date format in Java. And fail for other date patterns.
Happy Learning !!
Leave a Reply