JDK-6456628 : (tz) Default timezone is incorrectly set occasionally on Linux
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util:i18n
  • Affected Version: 5.0,6,6u10
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2006-08-03
  • Updated: 2011-11-29
  • Resolved: 2011-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7 Other
6u18Fixed 7 b72Fixed OpenJDK6Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) 64-Bit Server VM (build 1.5.0_06-b05, mixed mode)

  Bug also observed on 1.5.0_07.

Red Hat Enterprise Linux AS release 4 (Nahant Update 2)

Linux 2.6.9-22.20.ELsmp #1 SMP Fri Nov 18 03:04:44 EST 2005 x86_64 x86_64 x86_64 GNU/Linux

Time zone is set to America/New_York, and the system time should be within the EDT period

We have three identical Linux server and when we run the test case included below, the time reported by the machines are different.

By examining the available JVM source code, I noticed that the logic that works out the default timezone on Linux is incorrect.

The way JVM works out the default timezone is as follows:

1) Looks to environment variable TZ
This is not set in our linux box

2) JVM looks for the file /etc/sysconfig/clock and tries to find the "ZONE" entry.

However, on these host the ZONE entry does not have a double quote around the actual variable, and the JVM code is unable to recongise the entry.

3) If the ZONE entry is not found, the JVM will compare contents fo /etc/localtime with the contents of every file in /usr/share/zoneinfo recursively. When the contents matches, it returns the path and filename, referenced from /usr/share/zoneinfo

On our machine, there are three files in /usr/share/zoneinfo that matches /etc/localtime (these files are standard on RHEL4 machines):


What happens is that depends on the way OS transverse the filesystem, the name that JVM get can be different. On the box that fail the test, the jvm actually found posixrules file first, which means that the JVM thinks the timezone is "posixrules". The JVM will then attempt to look up timezone mapping in <java.home>/jre/lib/zi directory, and it will fail the find the timezone. So it will revert to the default GMT+offset timezone id as a fail safe, which does not take into the account for daylight saving.

We have three identical Linux server and ran the test case included below, the time reported by the machine is different.

(host 1)
bash-3.00$  date ; /opt/sunjava-1.5.0_06/jre/bin/java  simpleTest
Tue Aug  1 14:43:25 EDT 2006
Simple test Josh

Value of milliseconds  since Epoch is 1154457805659
Value of s  in readable format is Tue Aug 01 13:43:25 GMT-05:00 2006

(host 2)
bash-3.00$ date ; /opt/sunjava-1.5.0_06/jre/bin/java  simpleTest
Tue Aug  1 14:43:36 EDT 2006
Simple test Josh

 TIME ZONE :Eastern Standard Time
Value of milliseconds  since Epoch is 1154457816528
Value of s  in readable format is Tue Aug 01 14:43:36 EDT 2006

Notice that the default timezone returned by the systems are different.

The testcase should show the same time in readable format (like host 2)
During EDT, the printed time could be different from what we are expecting

This bug can be reproduced occasionally.

---------- BEGIN SOURCE ----------
import java.util.*;
import java.text.*;
class simpleTest
        public static void main(String args[])
           System.out.println("Simple test Josh ");

           Date now = new Date();
           DateFormat df = DateFormat.getDateInstance();
                Calendar cal = Calendar.getInstance();
        System.out.println("\n TIME ZONE :"+ cal.getTimeZone().getDisplayName());
           long nowLong = now.getTime();
           String s = now.toString();
           System.out.println("Value of milliseconds  since Epoch is " + nowLong);
           System.out.println("Value of s  in readable format is " + s);

---------- END SOURCE ----------

1) Set TZ to the correct timezone
2) pass -Duser.timezone with the correct timezone
3) make sure /etc/sysconfig/clock ZONE variable has quote around the value

EVALUATION The remaining work is to remove the /etc/sysconfig/clock support for RH and Fedora, and to add /etc/timezone support for Ubuntu (Debian distros).

EVALUATION RHES 5.3: /etc/sysconfig/clock contains ZONE as: ZONE="<olson_tzid>" such as ZONE="America/Los_Angeles" (uses double quotes and '_'). Fedora 11: /etc/sysconfig/clock contains ZONE as: ZONE="<system-config-date-tzname>" such as ZONE="America/Los Angeles" (uses double quotes and ' '). Both the operating systems suggest that /etc/sysconfig/clock be used only by system-config-date. So, Java shouldn't look up /etc/sysconfig/clock after all even it's very expensive to scan /usr/share/zoneinfo. The change to ignore "posixrules" was made as a 6533916 fix.

EVALUATION According to Red Hat documentation on /etc/sysconfig/clock, the ZONE value should be a file name. ZONE=<filename> ��� Indicates the timezone file under /usr/share/zoneinfo that /etc/localtime is a copy of, such as: ZONE="America/New York" http://www.redhat.com/docs/manuals/linux/RHL-7.2-Manual/ref-guide/s1-boot-init-shutdown-sysconfig.html So if the ZONE value is "America/New York", "/usr/share/zoneinfo/America/New York" should exist. It's not clear from the documentation, but the example uses ".

WORK AROUND One more workaround is to use a symlink for /etc/localtime. But it might cause some problems with Linux native code. Linux stopped using a symlink several years ago.

EVALUATION The time zone detection code for Linux was written around RedHat 6 or so. The code needs to be updated to deal with different Linux distributions.