« iCab 4.0.0 and iCab 3.0.5 Public Releases | Main | iCab 4.0.1 »
Thu, Jan 17, 2008
Parsing 2-Digit Years with Java's SimpleDateFormat
If you have to format and parse date strings like "17.01.2008" (in this case, the German date format) with Java, you'd probably use a java.text.SimpleDateFormat:
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
Date now = new Date();
System.out.println( sdf.format(now) ); // something like "17.01.2008"
Date then = sdf.parse( "17.01.1908" );
System.out.println( sdf.format(then) ); // "17.01.1908"
This works as expected. But now some fancy user dares to input the year with only two digits:
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
Date fancy = sdf.parse( "17.01.08" );
System.out.println( sdf.format(fancy) ); // "17.01.0008" - oops!
This is a feature that one easily fails to see in the API: If the year pattern is not "y" or "yy", year numbers are parsed literally and not relatively to some century. Using the short pattern works fine for parsing, but you'll need a second pattern for output:
SimpleDateFormat input = new SimpleDateFormat("dd.MM.yy");
SimpleDateFormat output = new SimpleDateFormat("dd.MM.yyyy");
Date ok1 = input.parse( "17.01.08" );
Date ok2 = input.parse( "17.01.2008" );
System.out.println( output.format(ok1) ); // "17.01.2008"
System.out.println( output.format(ok2) ); // "17.01.2008"
You can read (and set) the century offset using the property 2DigitYearStart.
And while we're at it: If you want to prevent SimpleDateFormat from parsing an illegal date like "32.01.2008", you'll have to switch off the lenient mode:
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yy");
sdf.setLenient( false );
Date illegal = sdf.parse( "32.01.1908" ); // ParseException