Check if String is valid Date in Java

java-logo2In Java, we play a lot with Dates. Here’s one more scenario. You have a string which has date in it. You want to convert it into a valid java.util.Date object. Now in Java you can convert a String to Date using SimpleDateFormat class. But we will add a little more complexity on that. Lets say the date format in String is not fixed. User might enter date in format “dd/mm/yyy” or “dd-mm-yyyy” or “dd.mmm.yy”!

In any of such case we should get a valid java.util.Date object.

Here’s a simple Util class that you can use to convert String having date in multiple formats to java.util.Date object.

package net.viralpatel.java;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class DateUtil {

	// List of all date formats that we want to parse.
	// Add your own format here.
	private static List<SimpleDateFormat>; 
			dateFormats = new ArrayList<SimpleDateFormat>() {{
			add(new SimpleDateFormat("M/dd/yyyy"));
			add(new SimpleDateFormat("dd.M.yyyy"));
			add(new SimpleDateFormat("M/dd/yyyy hh:mm:ss a"));
			add(new SimpleDateFormat("dd.M.yyyy hh:mm:ss a"));
			add(new SimpleDateFormat("dd.MMM.yyyy"));
			add(new SimpleDateFormat("dd-MMM-yyyy"));
		}
	};

	/**
	 * Convert String with various formats into java.util.Date
	 * 
	 * @param input
	 *            Date as a string
	 * @return java.util.Date object if input string is parsed 
	 * 			successfully else returns null
	 */
	public static Date convertToDate(String input) {
		Date date = null;
		if(null == input) {
			return null;
		}
		for (SimpleDateFormat format : dateFormats) {
			try {
				format.setLenient(false);
				date = format.parse(input);
			} catch (ParseException e) {
				//Shhh.. try other formats
			}
			if (date != null) {
				break;
			}
		}

		return date;
	}
}

The above code has a list of SimpleDateFormat objects that holds different valid date formats that you want to parse. Add a new format if you want your code to parse it.

Also check the convertToDate() method. It runs through each format from the list and check weather input string is valid date or not. If it is successful in converting String to Date, it returns the Date object. If it fails to convert String to Date then it returns null.

Let’s test this with various input:

package net.viralpatel.java;

public class TestDateUtil {

	public static void main(String[] args) {
		System.out.println("10/14/2012" + " = " + DateUtil.convertToDate("10/14/2012"));
		System.out.println("10-Jan-2012" + " = " + DateUtil.convertToDate("10-Jan-2012"));
		System.out.println("01.03.2002" + " = " + DateUtil.convertToDate("01.03.2002"));
		System.out.println("12/03/2010" + " = " + DateUtil.convertToDate("12/03/2010"));
		System.out.println("19.Feb.2011" + " = " + DateUtil.convertToDate("19.Feb.2011" ));
		System.out.println("4/20/2012" + " = " + DateUtil.convertToDate("4/20/2012"));
		System.out.println("some string" + " = " + DateUtil.convertToDate("some string"));
		System.out.println("123456" + " = " + DateUtil.convertToDate("123456"));
		System.out.println("null" + " = " + DateUtil.convertToDate(null));

	}	
}

Output:

10/14/2012 = Sun Oct 14 00:00:00 CEST 2012
10-Jan-2012 = Tue Jan 10 00:00:00 CET 2012
01.03.2002 = Fri Mar 01 00:00:00 CET 2002
12/03/2010 = Fri Dec 03 00:00:00 CET 2010
19.Feb.2011 = Sat Feb 19 00:00:00 CET 2011
4/20/2012 = Fri Apr 20 00:00:00 CEST 2012
some string = null
123456 = null
null = null

Thus you can quickly check weather given string is a valid Date or not using DateUtil class.

Update: SimpleDateFormat and Thread Safety

Many developers have commented on this post about the issue of Thread safety in this code snippet. As SimpleDateFormat class itself is not thread safe it can cause issues in production.

Here’s a workaround for this problem. Instead of SimpleDateFormat class in above utility method, use below ThreadSafeSimpleDateFormat class. This will solve the problem of Thread safety.

package net.viralpatel.java;

public class ThreadSafeSimpleDateFormat {

 private DateFormat df;

 public ThreadSafeSimpleDateFormat(String format) {
     this.df = new SimpleDateFormat(format);
 }

 public synchronized String format(Date date) {
     return df.format(date);
 }

 public synchronized Date parse(String string) throws ParseException {
     return df.parse(string);
 }
}

Thanks for your valuable comments :)



Tags: ,

15 Comments

  • Not Relevant 1 November, 2012, 13:52

    Try “DateUtil.convertToDate(“10/14/2012/01/01″)”

    • Viral Patel 1 November, 2012, 14:07

      Hi Not Relevant,
      SimpleDateFormat by default is set to Lenient true. Check here the javadoc. If you want to avoid such conditions, just add format.setLenient(true) right before you parse the date. It won’t consider the format 10/14/2012/01/01.

      • Not Relevant 2 November, 2012, 18:36

        Give it a try first. Here’s the code again:

            final SimpleDateFormat sdf = new SimpleDateFormat("yyyy.mm.dd");
            sdf.setLenient(true);
            Date date = null;
            try {
              date = sdf.parse("2012.11.02.45.65");
            } catch (ParseException e) {
              e.printStackTrace();
            }
            // Output: date: Mon Jan 02 00:11:00 FET 2012
            System.out.println("date: " + date);
        
        • Viral Patel 2 November, 2012, 18:54

          Ops, my bad.. I meant

          setLenient(false);

          By default SimpleDateFormat set Lenient to true. So we should set it false if we want strict checkup.

  • timoras 2 November, 2012, 10:09

    one more thing. frm java doc abouyt simpleDateFormat

    Synchronization

    Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.
    Just keep in mind

  • Frantisek 2 November, 2012, 12:20

    Using date format with separators is realy simple, but how would you deal with format like “ddMMyy”?

    And user input like : “11111”. it could be both 1.11.2001 and 11.1.2011 :-)

  • Frisian 2 November, 2012, 13:05

    Even if you set lenient to false, a format like “dd.MM.yyyy” will happily accept a two-digit year with possibly surprising results. The solution i’ve seen at almost every company I worked with was to accompany every date format with a corresponding regex. The regex is checked first to unambiguously map the input to the appropriate date format.

    • Viral Patel 2 November, 2012, 14:32

      Hi Frisian, Can you share a snippet for that! Would be interesting to check.

      • Frisian 2 November, 2012, 18:32

        Hi Viral,

        I’m under NDA, but I am probably allowed to outline the matching:
        For the date format “dd.MM.yyyy”, the equivalant regex would be “\\d\\d[.]\\d\\d[.]\\d\\d\\d\\d”.
        The code inside a loop for the different date formats would look something like this:

        ...
        Pattern p = Pattern.compile(regex); // thread-safe
        ...
        Matcher m = p.matcher(input);
        if (m.matches()) {
          SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
          sdf.setLenient(false);
          return sdf.parse(input);
        }
        // exception handling goes here
        ...
        

        The problem with the non-thread-safe SimpleDateFormat is solved as well.

  • NotThreadSafe 2 November, 2012, 18:51

    That is not thread safe and will cause inconsistent results when . You are going to wreck someones month if you don’t put a disclaimer on that it is not production ready

    • Viral Patel 2 November, 2012, 19:10

      Hi, I understand that the code isn’t thread safe. But I presented here it in its entirety for reference purpose. Anyways, I have updated the post and added a new “Thread Safe” version which will solve this issue.

      Thanks,
      Viral

  • Abhishek Prartap Singh 19 April, 2013, 17:41

    sir I want to convert a date which is in String format of “dd/mm/yyyy” . now I want to convert this string in ‘dd/MON/yy” as a Date in Java.

    Example: “19/04/2013″ should be converted in 19/APR/13 in Java

  • Gowtham 27 October, 2013, 0:30

    Isn’t there any other alternative to it because this seems to be an awkward practice (don’t take my wrong) because in any situation, we need to try our level best to prevent an exception to occur.

    Thanks.

  • M 7 December, 2013, 8:00

    Hi,

    I want to do a filename validation that has date in it. For Example, Mad20131222.txt .. i.e. Date should be in format YYYYMMDD. Appreciate your help in this regard

    Thanks!

  • MeSh 12 June, 2014, 17:42

    consider this case…
    You have set the date format as dd-mm-yyyy
    however your input string is “08-09-2014 any junk afterwards”
    This input string will also get processed, try it out.
    Let me know what are your thoughts about how to handle this ?

Leave a Reply

Your email address will not be published. Required fields are marked *

Note

To post source code in comment, use [code language] [/code] tag, for example:

  • [code java] Java source code here [/code]
  • [code html] HTML here [/code]

Current ye@r *