A couple of weeks ago, on New Year’s Eve, one of our nightly builds suddenly broke because of a spontaneously failing unit test. The next day everything worked again without anyone having been able to touch the code (because the office was closed ;)).
The culprit turned out to be one of the unit tests that was testing some trivial date conversions. In the assertions we’d happened to use a SimpleDateFormat
.
|
@Test public void localDateToSqlDate() throws Exception { assertNull(Dates.fromLocalDate(null)); final Date sqlDate = Dates.fromLocalDate(nowLDT.toLocalDate()); assertNotNull(sqlDate); final SimpleDateFormat sdf = new SimpleDateFormat("YYYYMMdd"); final String sqlDateFormatted = sdf.format(sqlDate); assertEquals(nowLDT.toString(DateTimeFormatter.BASIC_ISO_DATE), sqlDateFormatted); } |
org.junit.ComparisonFailure: expected:<201[4]1231> but was:<201[5]1231>
at org.junit.Assert.assertEquals(Assert.java:115)
...
There are alot of issues with SimpleDateFormat
, such as its performance being suboptimal and most of all it not being threadsafe, but these we were aware of. What we didn’t now at the time, was the difference between using the pattern letters ‘y
‘ and ‘Y
‘.
Whether you format a date using the pattern ‘yyyyMMdd
‘ or with ‘YYYYMMdd
‘, one would expect the outcome to reflect the year of the date you’re formatting. But as it turns out, December 31st can occur in the first week of the new year, resulting in an incorrect year.
My takeaway, don’t ever use the Week year pattern ‘Y’.