• In Java (SimpleDateFormat), the date format “YYYY” returns the “week based year
    • The week based year is not always equal to the year (“yyyy”).
  • The format (specially “Y”) depend on the library you use. Read the doc when:
    • you have some doubts
    • you just changed date (formatting) library
    • you didn’t read it for some times
  • Week based years are cool, but not when classic years are expected

TL;DR

Some of you may have be aware of a incident in the Twitter’s Sign-in process, due to a stupid bug: the Twitter’s servers returned the date “2015-12-29” instead of “2014-12-29”:

The cause was easy to catch: the returned date was formatted using the Week based Year, as part of the ISO 8601 specification.

Week based year

The idea of this format is simple: it is a way to reference a specific day of the calendar.

We often specify the day’s year, then the day’s month and finally the position of the day in its month. The standard (ISO 8601) format is: “<year>-<month-of-year>-<day-of-month>”. For instance “2014-12-29”.

We might also specify the day’s year then the position of the day in the year (“2014-363”). This is called “ordinal date” by this standard.

The week based format uses the week instead of the month: “<year>-W<week-of-year>-<day-of-week>”. The problem of this format is the year limit: December the 31th and January the 1st often belong to the same week, so which format to choose: “2014-W53-4” or “2015-W01-4”? The year 2014 has only (oO) 52 weeks, so the valid format is “2015-W01-4”. Yes, “2015”.

In order to be able to write this format, a special notation has been introduced: the week based year (often called “week year” in library’s documentations), which is the year of the week according to the ISO 8601 specification.

Here is an example, using the shell command date:

# display the full date
$ date -j -f %s 1419841228
# => Mon 29 dec 2014 17:20:28 JST
# display the year
$ date -j -f %s 1419841228 +%Y
# => 2014
# display the week based year
$ date -j -f %s 1419841228 +%G
# => 2015

(note: the “-jis important—if you want to keep your system’s date unchanged)

It minded me a little: how can people use the week based year by mistake? Specially people which coded the Twitter’s API, a highly critical part of this heavily used application.

So I checked how to format the year in some library, here what I found:

Quick-and-dirty status of some existing date formatters

(Standard) Libraries

  • PHP
    • Y = year (4 digits)
    • y = year (2 digits)
    • o = week based year (4 digits)
  • Javascript - Moment.js
    • YYYY = year
    • gggg = week year
    • GGGG = ISO week year (weeks start on Monday)
  • .NET (I couldn’t find a proper URL)
    • YYYY / yyyy = year
  • Java - SimpleDateFormat
    • YYYY = week based year ← big problem right here
    • yyyy = year
  • Java - Joda-Time
    • YYYY = year of era ← problem right here
    • yyyy = year
    • xxxx = week based year
  • C - strftime

Specs

  • W3C
    • Nothing specified ( “Year: YYYY (eg 1997) […] where: YYYY = four-digit year”)
  • LDML/CLDR Spec
    • Nothing specified (closer: “Characters may be used multiple times. For example, if y is used for the year, ‘yy’ might produce ‘99’, whereas ‘yyyy’ produces ‘1999’”)

Thanks Java for providing highly dangerous behavior for common characters ☺︎.

Note: Using Year of Era is not that buggy (Gregorian calendar didn’t change era for centuries)… until you need to handle them, right?

My so-waited-and-so-precious point of view

If you are not 100% confident in the format you chose, go and read the doc.

The real problem of these different behaviors is not that they can lead to different result (since there is no standard), but it is that some of these different behaviors occur only few times a year. So: you test your code, it works, you are confident, you put it in production, it fails some month later, you don’t know where to look at, it is plus ungood.

Conclusion: This particular 2014’s bug is resolved now that we are in 2015 and the next occurrence will wait until January 2016 (where “2015” will be returned the 4 first days), so you can forget about this post for now, there is absolutely no reason something could go wrong.

PS: pardon my English.