Buggy dates in Java

May 20th, 2005

That the Date and Calendar classes in Java are hard to work with, that's a fact we're all familiar with. But today, I bumped into something that seriously looks like a bug to me. Consider the following lines of code: Date date = new GregorianCalendar(2002, Calendar.DECEMBER, 30).getTime(); DateFormat format = new SimpleDateFormat("yyyyww"); format.getCalendar().setFirstDayOfWeek(Calendar.MONDAY); format.getCalendar().setMinimalDaysInFirstWeek(4); System.out.println(format.format(date)); Now, what's the output you would expect from this? My first guess would be "200252" or maybe even "200253". But when you start thinking about it, you start to wonder to which year a week really belongs to. So maybe even "200301" wouldn't surprise you too much. But the proof of the pudding is in the eating, so you run the program. And your jaw drops to the ground when you see the output: 200201Huh? How can December 30 possibly be in the first week of the year? After some googling, surfing, studying the sun and the stars, and reading all about standards, legislation, and ISO 8601, you get the feeling: I found a bug! So one goes to java.sun.com's bug database, and checks for the bug's existence. And what does one find? This. So the bug has been reported, and has been dismissed as "not a bug". But I really don't understand the reviewer's explanation: how can a day in December be in the first week of the year? Now, I found a workaround using Jodatime, which goes as follows: Date date = new GregorianCalendar(2002, Calendar.DECEMBER, 30).getTime(); DateTimeFormatter fmt = ISODateTimeFormat.weekyearWeek(); String result = fmt.print(new DateMidnight(date)).replaceAll("-W", ""); System.out.println(result); Which showed me the result I ended up expecting:200301But still, if anybody could shed some light on the JDK's behaviour, I would greatly appreciate it. My intellectual curiosity just isn't satisfied.

5 Responses to “Buggy dates in Java”

  1. Stephen Colebourne Says:
    Your date is 2002-12-30. So, the JDK returns 2002 because that is the year you requested in the date! What you are expecting the JDK to return is the weekyear - ie. the year in which the week falls. The ISO8601 standard defines how this is calculated, and for this date it is 2003-W01 (weeks are always complete, thus weeks can overlap into previous or following real years). Hence the JDK is not wrong, just incomplete - it provides no way to get the weekyear. For Joda-Time, you could optimise your result slightly by using DateTimeFormatter fmt = new DateTimeFormatterBuilder() .appendWeekyear(4, 4) .appendWeekOfWeekyear(2) .toFormatter(); String result = fmt.print(new DateMidnight(date)); (and the formatter can be stored in a static constant)
  2. Tom Klaasen Says:
    Stephen: if you tell the story like this, it seems to make sense. I'm still glad I could use Jodatime though :) Thanks for your insight!
  3. Brian S O'Neill Says:
    You can make the code even simpler by using DateTimeFormat and the pattern "xxxxww". The xxxx pattern is unique to Joda, which means weekyear instead of year. DateTimeFormatter fmt = DateTimeFormat.forPattern("xxxxww"); String result = fmt.print(new DateMidnight(date));
  4. Tom Klaasen Says:
    Brian: thanks, that solution seems to work fine, too (and is indeed a tad simpler than mine :) )
  5. kishoreg Says:
    Thanks for this Tom. I encountered the same problem and used joda-time to solve it. But I have a small problem the week in joda-time starts from Monday where as jdk week starts from Sunday. I cant use joda-time because we have been using the jdk convention and it is difficult to change that convention now. Is there a way to tell joda-time to start the week from Sunday instead of Monday. As per my knowledge both conventions are valid but it will be nice if there is a way to specify which convention to use. For example Unix date command provides this option date -d '20041231' +%Y%V - starting from monday date -d '20041231' +%Y%U - starting from sunday

Leave a Reply