Java timezone madness

September 9, 2014|Posted in: Java, Web Application Programming

I was recently working on a legacy java servlet application and ran into an interesting problem.

It seems that somewhere between Java 5 and Java 7 there were some changes to the way timezones are handled. The application was reading and writing dates to the database, and web page, but for some reason the time was fluctuating by 1 hour in the database.

Ordinarily this wouldn’t have been a big deal since we really only worried about the date portion for display, but since we were using the hour portion in calculations and it was set to 23:59:59, well you can see the problem. When I checked the first bit of source code, I found that it was calling a really nice function from an internal library where it set the timezone and then formatted the string the way we wanted it displayed on the screen and I thought well it can’t be code it must be something with the OS or Database.

I spent 2 weeks working with the System Administrators and checking the system settings, the time source for the network time and many other factors and we could not find anything amiss. I went back in and checked the code again, and found this little gem buried in some of the pages:

DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
String datePosted = getParameter(req, "datePosted", df.format(new Date()));

Notice that at no time was the timezone set, but according to the documentation, it will use the system settings which in this case are America/New_York. Wondering if this lack of the timezone setting which was so nicely handled in the library was the source of the problem, I put together a quick application to print out the default settings and the ones from the library.

package tzinfo;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.text.DateFormat;

public class Info {

public static void main(String[] args) {
Date d = new Date();
DateFormat df = new SimpleDateFormat(“MM/dd/yyyy HH:mm”);
TimeZone tz = TimeZone.getTimeZone(“America/New_York”);
String utilStyle = format(d, “MM/dd/yyyy HH:mm”);
String simpleStyle = df.format(d);

System.out.printf(“Utility Style %s, Simple Style %s %n”, utilStyle, simpleStyle);
System.out.printf(“here is the tz for the df %s %n”, df.getTimeZone().toString());
}
public static String format(Date date, String pformat) {
TimeZone tz = TimeZone.getTimeZone(“America/New_York”);
TimeZone.setDefault(tz);
System.out.printf(“The timezone information is %s %n”, tz.toString());
String retVal = “”;
SimpleDateFormat date_format = new SimpleDateFormat(pformat);
if (date == null) {
return retVal;
}
date_format.setTimeZone(TimeZone.getDefault());
retVal = date_format.format(date);
return retVal;
}
}

The results from running that code gave me this:

The timezone information from the Library is sun.util.calendar.ZoneInfo[id=”America/New_York”,offset=-18000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/New_York,offset=-18000000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]]
Utility Style 09/09/2014 11:07, Simple Style 09/09/2014 10:07

The timezone information from the SimpleDateFormat is sun.util.calendar.ZoneInfo[id=”GMT-05:00″,offset=-18000000,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]

Notice that in the library useDaylight=true in the Library, and in the SimpleDateFormat useDaylight=false. Since both of the usages were scattered throught the code base, and I needed an immediate fix, I added the following to the JVM that was running the Tomcat container: -Ddefault.timezone=America/New_York That forces the the default timezone to match what is used in the library and keeps the dates correct.

While this isn’t optimal, it is the best I could do without making wholesale changes to the code and database. In the future, I would recommend that dates be stored in the database as GMT and then displayed using the appropriate timezone conversion. This being used in conjunction with a good framework that supports internationalization, will allow you to support providing dates and times in local time and format when needed or forcing them to display in a specific timezone.

General purpose computer geek.