While I have the fortune of running Ubuntu and Debian at home, I have the misfortune of working with Red Hat (Fedora Core 9, specifically) at the office. Today, I spent the afternoon fighting Java, which insisted that the time was an hour earlier than reality. I found a solution.
So here's the environment. My computer lives in Eastern Daylight Time (UTC-04:00 at this time of year). Obviously, when Daylight Saving Time is not in effect, we're five hours behind UTC. My system is "properly" configured, with the time zone set to "America/New_York". My test program looks like this:
Listing:
import java.util.*; public class Test { public static void main(String args[]) throws Exception { System.err.println("Default TZ="+TimeZone.getDefault()); System.err.println("Now="+new Date()); } }Output:
$ date Fri Jun 20 17:17:09 EDT 2008 $ java Test Default TZ=sun.util.calendar.ZoneInfo[id="GMT-05:00",offset=-18000000, dstSavings=0,useDaylight=false,transitions=0,lastRule=null] Now=Fri Jun 20 16:17:09 GMT-05:00 2008
As you can see, it reports the non-DST version, because it's really just guessing. And it is also off by an hour. After reviewing a ton of literature and discussion online, the most commonly accepted work-around for this issue is to specify the TZ environment variable, which should be totally unnecessary. But it works:
Output:
$ date Jun 20 17:22:04 EDT 2008 $ TZ="America/New_York" java Test Default TZ=sun.util.calendar.ZoneInfo[id="America/New_York",offset=-18 000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=ja va.util.SimpleTimeZone[id=America/New_York,offset=-18000000,dstSavings =3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDa y=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMo nth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]] Now=Fri Jun 20 17:22:04 GMT-04:00 2008
But I was not satisfied by this... if the OS is properly configured, and Java is anything better than brain-dead, it should work. So I pulled out my trusty "strace" tool, for following system calls. You have to remember to use the "-f" parameter, so that it actually digs down into the useful child processes that get spawned.
What I ended up finding was that it was trying to open the file
$JRE_HOME/lib/zi/America/New York
. Looking in that
directory, I found a file named New_York
— with an underscore,
instead of a space. Now, I'm not sure where it is getting a time zone name
with a space instead of an underscore, but the solution was immediately
obvious to me. Create a symbolic link to the underscore version using a
name with a space:
Output:
$ su - Password: # cd $JRE_HOME/lib/zi/America # ln -s New_York New York # logout $ date Fri Jun 20 17:31:17 EDT 2008 $ java Test Default TZ=sun.util.calendar.ZoneInfo[id="America/New York",offset=-18 000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=ja va.util.SimpleTimeZone[id=America/New York,offset=-18000000,dstSavings =3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDa y=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMo nth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]] Now=Fri Jun 20 17:31:10 GMT-04:00 2008
I have to wonder if this only shows up for people with a space in their time zone name, like America/Los_Angeles and America/New_York. If that's the case, making that symbolic link might be the best solution for you, as it doesn't rely on system configuration. I hope this is useful for other folks, so they don't have to bash their heads against the wall for hours like I have. Good luck!