Wednesday, November 18, 2009

More GWT Date woes

So, as we all know, working with dates in GWT is not much fun given the lack of a Calendar class to do any sort of date manipulation. Incrementing and decrementing dates must now be done by adding and subtracting from the milliseconds that have elapsed since epoch.

So we have a method that does the calculating for you and it has been working fine, until I stumbled upon a very interesting bug. Apparently, there is some issue revolving around November 1, 2009. Here some some code to replicate my results:
public void onModuleLoad()
{
DateTimeFormat format = DateTimeFormat.getFormat("dd/MM/yyyy H:mm:ss");
String dateString = "01/11/2009 1:30:30";

Date originalDate = format.parse(dateString);
Date date = new Date();

for (int i = -7; i < 8; i++)
{
date = incrementDays(originalDate, i);
System.out.println("DateUtil.incrementDay(" + i + ") = " + date.toString());
}
}

private static Date incrementDays(Date date, int xdays)
{
long time = date.getTime();
time = time + (xdays * 24 * 60 * 60 * 1000);

Date newDate = new Date(time);
return newDate;
}
Here is the output from this test:
DateUtil.incrementDay(-7) = Sun Oct 25 02:30:30 CDT 2009
DateUtil.incrementDay(-6) = Mon Oct 26 02:30:30 CDT 2009
DateUtil.incrementDay(-5) = Tue Oct 27 02:30:30 CDT 2009
DateUtil.incrementDay(-4) = Wed Oct 28 02:30:30 CDT 2009
DateUtil.incrementDay(-3) = Thu Oct 29 02:30:30 CDT 2009
DateUtil.incrementDay(-2) = Fri Oct 30 02:30:30 CDT 2009
DateUtil.incrementDay(-1) = Sat Oct 31 02:30:30 CDT 2009
DateUtil.incrementDay(0) = Sun Nov 01 01:30:30 CST 2009
DateUtil.incrementDay(1) = Mon Nov 02 01:30:30 CST 2009
DateUtil.incrementDay(2) = Tue Nov 03 01:30:30 CST 2009
DateUtil.incrementDay(3) = Wed Nov 04 01:30:30 CST 2009
DateUtil.incrementDay(4) = Thu Nov 05 01:30:30 CST 2009
DateUtil.incrementDay(5) = Fri Nov 06 01:30:30 CST 2009
DateUtil.incrementDay(6) = Sat Nov 07 01:30:30 CST 2009
DateUtil.incrementDay(7) = Sun Nov 08 01:30:30 CST 2009
As you can see, at November 1, the time gets decremented by one hour. I have not been able to figure out what exactly is causing this. I have run a ton of tests and have not been able to come up with any answers. All other dates in 2009 appear to work (although, I did not test them all). Also, November 1, 2010 does work, but it is off again on November 8.

Just another reason why we need a Calendar class for GWT.

If anyone has any ideas what is causing this, please let us know.


UPDATE:
Day light savings time did not cross my mind, and is seems to be the culprit in this issue. If anyone has any other ways of calculating the date on the client side in GWT, let us know. Thanks.


UPDATE #2:

Here is the new incrementDays() method to deal with this issue:

private static Date incrementDays(Date date, int xdays)
{
long time = date.getTime();
time = time - (xdays * 24 * 60 * 60 * 1000);

Date newDate = new Date(time);

Integer dateHour = new Integer(DateTimeFormat.getFormat("H").format(date));
Integer newDateHour = new Integer(DateTimeFormat.getFormat("H").format(newDate));
if (!dateHour.equals(newDateHour))
{
if (dateHour > newDateHour || (dateHour.equals(0) && newDateHour.equals(23)))
{
time = time + (60 * 60 * 1000);
newDate.setTime(time);
} else if (dateHour < newDateHour)
{
time = time - (60 * 60 * 1000);
newDate.setTime(time);
}
}

return newDate;
}