Java SimpleDateFormat gives wrong results

Would you expect the following lines of code to ever print something to the standard output?

public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
...
Date date = dateFormat.parse("2012-10-26");
String reformat = dateFormat.format(date);
if (!"2012-10-26".equals(reformat)) {
  System.out.println("Wrong date: " + reformat);
  }

Indeed, there are situations when such code will occasionally fail.
The SimpleDateFormat class is not thread safe, that means whenever two or more separate threads access the same class instance, the results from the parse() and format() methods can produce wrong results.
To reproduce this effect, I show the full test code:

package com.udojava.blog;

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

public class DateFormatDemo {

	public static SimpleDateFormat dateFormat = new SimpleDateFormat(
			"yyyy-MM-dd");

	public class DemoThread extends Thread {

		@Override
		public void run() {
			for (int i = 0; i < 100; i++) {
				try {
					Date date = dateFormat.parse("2012-10-26");
					String reformat = dateFormat.format(date);
					if (!"2012-10-26".equals(reformat)) {
						System.out.println("Wrong date: " + reformat);
					}
				} catch (ParseException e) {
					e.printStackTrace();
				}
			}
		}

	}

	public void testRun() {
		DemoThread t1 = new DemoThread();
		DemoThread t2 = new DemoThread();
		t1.start();
		t2.start();
	}

	public static void main(String[] args) {
		new DateFormatDemo().testRun();
	}

}

If you run this, you will get differing outputs from one run to the next run, something like this:

Wrong date: 2201-10-26
Wrong date: 2201-10-26
Wrong date: 2012-12-26
Exception in thread "Thread-1" java.lang.NumberFormatException: empty String
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1011)
at java.lang.Double.parseDouble(Double.java:540)
at java.text.DigitList.getDouble(DigitList.java:168)
at java.text.DecimalFormat.parse(DecimalFormat.java:1321)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2088)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at com.udojava.blog.DateFormatDemo$DemoThread.run(DateFormatDemo.java:18)

So, sometimes it can be dangerous to try to over-optimize by using static members that are shared between threads. Even simple things like a SimpleDateFormat can fail in multithreading.
And they usually then fail only in 1 out of 1000 times, making it a real horror to find, debug and fix those issues.

Advertisements

3 Responses to Java SimpleDateFormat gives wrong results

  1. Pingback: The Unparseable Date Pitfall « Udo's Java Blog

  2. Peter says:

    “And they usually then fail only in 1 out of 1000 times, making it a real horror to find, debug and fix those issues.”

    So true!

  3. JP says:

    Thank you!! Saved a lot of time for me…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: