www.brianziman.com
Linux – Java – Web – Questions Answered, Problems Solved

Wrong Default TimeZone in Java on Red Hat Linux (Friday, June 20, 2008)

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!

—Brian (6/20/2008 5:35 PM)
(5 comments)

Comments

Thank you for documenting this. I'm running Fedora 9 in the "New York" zone and the symlink trick worked for me.

-- (7/9/2008 3:58 PM)

Same problem and same solution for the Los Angeles time zone. Thanks for the fix.

-- (8/27/2008 6:43 PM)

I had the same issue in FC9 since I am also in the America/New_York timezone. My fix was to edit /etc/sysconfig/clock since strace showed me it that syscalls originating from Java were reading that file. Turns out that it was the source of "America/New York". I updated the ZONE variable in the file as follows:

----
# The ZONE parameter is only evaluated by system-config-date.
# The time zone of the system is defined by the contents of /etc/localtime.
#ZONE="America/New York"
ZONE="America/New_York"
----

Java worked like a charm after that. I'm not sure if this will cause downstream problems in FC9 in the event that other programs and such are depending on the value ZONE="America/New York", but the file comments in /etc/sysconfig/clock quoted above seem to imply that the change is low risk.

-- Jeff Metcalf (9/12/2008 12:19 PM)

Good detective work guys! I ran into this same problem today, and you saved me some troubleshooting to figure out what was going on. I've reported this as a bug to the Fedora team:

https://bugzilla.redhat.com/show_bug.cgi?id=489586

You might want to vote for it to raise the visibility.

-- Kartik Subbarao (3/10/2009 3:36 PM)

Jeff's workaround, changing /etc/localtime is probably better than my approach of creating symlinks, though the symlink approach won't break whenever Redhat fixes their system, which can't be guaranteed for the localtime change...

-- Brian (6/17/2009 10:41 PM)

Name
URL
Comment
(no html)
 

Disclaimer: Opinions on this site are those of Brian Ziman and do not necessarily
reflect the views of any other organizations or businesses mentioned.