« 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