Java Strict Date Validation – Java SimpleDateFormat setLenient() Method

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 !!

Ref – SimpleDateFormat Java Doc

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

11 thoughts on “Java Strict Date Validation – Java SimpleDateFormat setLenient() Method”

  1. Hi, I’m getting below validation error while unmarshaling my xml file

    cvc-datatype-valid.1.2.1: ‘2019-02-19T14:34:40+03’ is not a valid value for ‘dateTime’.

    Please help me for resolve it.

    Thanks,
    Pawan

    Reply
  2. Even if you use setLenient to FALSE, in the cases that the intervals are acceptal but the format is not, the parse will result in success.
    To avoid it, use format over the parse result Date and compare with “equals” the initial String date.

    Reply
  3. I tried to parse this date “2014-100-11 22:53:45” and guess what it parsed!!!!….no error!!!!

    and also sometimes my simpledateformatter returns date in format like ‘2014-0011-20 21:53:45 ‘. How it can be?

    Reply
  4. Hi Lokesh,
    JAXB is not populating the dateTime fields with joda DateTime values
    @XmlElement(name=”joindate”)
    private DateTime joinDate;

    I don’t see any error in the log as well because it is generating as empty tag.

    Reply

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.