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

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)

2 thoughts on “Java SimpleDateFormat and 4-digit year vs. 2-digit year

Leave a Reply