Skip to main content
mbehan

Death By Date Format String

Recently I learned that you probably always want "yyyy" and not "YYYY".

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "YYYY-MM-dd"

println(dateFormatter.stringFromDate(
   dateFormatter.dateFromString("2015-12-26")!))

This prints 2015-12-26. Obviously. So what about

println(dateFormatter.stringFromDate(
   dateFormatter.dateFromString("2015-12-27")!))

It prints 2016-12-27.

Note that the year is 2016.

I was fortunte[^1] enough to get assinged a production crash bug this week that after a long day of head scratching, turned out to be caused by this.

Interestingly, the NSDate created with the format is the date I expected, it represents 27 December 2015 and it's only getting a string from the date with that format that gives you the 'wrong' year. Similarly an NSDate constructed in any other way that represents 27 December 2015 will behave the same.

The NSDateFormatter docs point you at Unicode Technical Standard Number 35 for the definitions of date format strings. I've looked at this before and I expect I'm not alone in having paid more attention to the day and month parts of the format. They're usually what we're interested in because the year is always the year, at most we might prefer 2 or 4 digits but thats about as interesting as it gets. I suspect what happens fairly often (and what probably happened with our bug) was that the developer guessed at YYYY as the year format, and when it appeared to work just fine, assumed it was correct.

The relavant part of that standard states that y is the year, but Y is

Year (in "Week of Year" based calendars) ... May not always be the same value as calendar year.

And the problem is that, as far as I can tell, it almost always is the same as the calendar year. The last few days of the year are the only ones I've seen causing problems. If it was more different, it would be spotted easier and perhaps I would have already known that YYYY was wrong and spotted that as the error right away.

[^1]: If I consider it a learning opportunity and not an annoying time suck of a bug!