my2cents

15. April, 2008

Java SimpleDateFormat and 4-digit year vs. 2-digit year

Filed under: Java,Software Development — frightanic @ 23:35

This blog now resides at http://www.frightanic.com/. It will be discontinued here…

At the end of an already long day a co-worker and I recently came across the problem that

new java.text.SimpleDateFormat("dd.MM.yyyy").parse("03.03.08");

does not return March 3rd, 2008 but March 3rd, 0008 instead.

As any decent engineers would, we headed for the respective API documentation right away to see whether there was an explanation for this behavior. Like any bad engineers, however, we didn’t pay close enough attention to the details in the documentation and tried to fix the problem with the wrong tools. Since our customer forces us to develop for the WebSphere platform, hence for an IBM Java runtime, we even suspected that this might be the cause for our confusion. Shame on us! We were barking up the wrong tree. It’s all there in the JavaDocs if you read it carefully: http://java.sun.com/j2se/1.5.0/docs/api/java/text/SimpleDateFormat.html#year:

“For parsing, if the number of pattern letters is more than 2, the year is interpreted literally, regardless of the number of digits. So using the pattern “MM/dd/yyyy”, “01/11/12″ parses to Jan 11, 12 A.D.”

Ok, that’s the explanation, but what is the solution if you need “03.03.08” or “03.03.2008” to be parsed into March 3rd, 2008? As so very often I needed to put some distance between myself and the problem (it dawned on me in the train on my way home). The pattern in this case needs to contain fewer or an equal number of letters for the year than the actual string to be parsed. The pattern “dd.MM.yy” interprets both the above examples as March 3rd, 2008.

For testing purposes I wrote a few lines of code to observe the behavior of the parse() method.

import java.text.*;
public class DateTest {
    private static final DateFormat parseFormat = new SimpleDateFormat("dd.MM.yy");
    private static final DateFormat formattingFormat = new SimpleDateFormat("dd.MM.yyyy");

    public static void main(String[] args) throws ParseException {
        test("3.3.08");
        test("3.3.2008");
        test("03.03.08");
        test("3.3.08xx");
        test("32.3.08");
        test("3.3.xx08");
    }

    private static void test(String dateString) throws ParseException {
        System.err.println(formattingFormat.format(parseFormat.parse(dateString)));
    }
}

produces

03.03.2008
03.03.2008
03.03.2008
03.03.2008
01.04.2008 // obvious, due to default lenient behavior
Exception in thread "main" java.text.ParseException: Unparseable date: "3.3.xx08"
	at java.text.DateFormat.parse(DateFormat.java:335)
	at DateTest.test(DateTest.java:16)
	at DateTest.main(DateTest.java:12)
Advertisements

3 Comments

  1. Thanks for the post, this saved lots of time and frustration with Date formatting

    Comment by Jason P — 9. December, 2008 @ 19:03

    • Glad I could help. Very often blog entries from other developer help me solve problems. So, I feel I need to give back something.

      Comment by frightanic — 9. December, 2008 @ 19:24

  2. This was causing me a headache – thank you!

    Comment by fullsteam — 12. December, 2011 @ 22:33


RSS feed for comments on this post.

Blog at WordPress.com.

%d bloggers like this: