Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 6456628
Votes 25
Synopsis (tz) Default timezone is incorrectly set occasionally on Linux
Category java:classes_util_i18n
Reported Against
Release Fixed 7(b72), 6u18(b02) (Bug ID:2180391)
State 10-Fix Delivered, bug
Priority: 3-Medium
Related Bugs 6533916 , 6609348 , 6626679 , 6645293 , 6845672 , 6849350 , 6856174 , 2179642 , 6893624
Submit Date 03-AUG-2006
Description
FULL PRODUCT VERSION :
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.

ADDITIONAL OS VERSION INFORMATION :
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


EXTRA RELEVANT SYSTEM CONFIGURATION :
Time zone is set to America/New_York, and the system time should be within the EDT period

A DESCRIPTION OF THE PROBLEM :
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):

/usr/share/zoneinfo/America/New_York
/usr/share/zoneinfo/posixrules
/usr/share/zoneinfo/EST5EDT

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.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
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

 TIME ZONE :GMT-05:00
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.


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

REPRODUCIBILITY :
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 ----------

CUSTOMER SUBMITTED WORKAROUND :
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
Posted Date : 2006-08-03 07:11:35.0
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.
Posted Date : 2006-08-03 07:38:20.0

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 ".
Posted Date : 2009-03-16 04:16:42.0

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.
Posted Date : 2009-07-21 06:38:15.0

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).
Posted Date : 2009-08-07 05:19:25.0
Comments
  
  Include a link with my name & email   

Submitted On 05-MAY-2007
Jetly
In Windows 

the TimeZone.getDefault().getID()  is returning      "GMT+05:50" farmat but in

Linux it is returning "Europe/London" format 

I think it should be unique to Linux and Windows


Submitted On 10-MAY-2007
There has been quite an interesting discussion about this bug and possible fixes in the bug tracker of Ubuntu's bug tracker.

Ubuntu does not use neither TZ nor /etc/sysconfig/clock, and /etc/localtime is a regular file. Scanning the time zone database may cause problems as Ubuntu's /usr/share/zoneinfo directory contains a symbolic link to /etc/localtime, which can cause time zone detection to fail depending on the order the files are read.

However, Ubuntu has /etc/timezone, which includes the time zone (Europe/Amsterdam in my case) and nothing else.

Another fix might be to rewrite the scanning of /usr/share/zoneinfo to continue if a file is found that is identical to /etc/localtime, but whose name does not correspond to time zone known to Java.

This would solve the bug described here for Red Hat as well as the bug in Ubuntu.

See
https://bugs.launchpad.net/ubuntu/+source/sun-java5/+bug/49068

Christian Assig


Submitted On 10-MAY-2007
> in the bug tracker of Ubuntu's bug tracker.
Sorry, I meant the bug tracker of Ubuntu's Java package


Submitted On 06-JUL-2007
650775
I found that having a space in the ZONE value of /etc/sysconfig/clock didn't work (even with double quotes ["] around it).  I had to replace the space with an underscore [_]:
ZONE="America/Los Angeles"
chaged to:
ZONE="America/Los_Angeles"

Is this a bug with the way Java is parsing this file or with the way it is written by a desktop app?


Submitted On 29-AUG-2007
I had the same problem with 64-bit debian etch (4.0) and java 1.5.0_10. I too read the sourcecode, before finding this bug entry, and fixed it by making /etc/localtime a symlink.

Oddly on my Ubuntu 6.06.1 with Java 6.0_00 /etc/localtime is already a symlink, I cannot remember altering it myself. The symlink appears to have been last modified when installing the latest locales-2.3.18.4 package update.

Regards,
Stefan


Submitted On 16-OCT-2007
abridgett
Here this is breaking badly  - it uses /usr/share/zoneinfo/localtime which is a symlink so it get's confused.
If I remove that then it thinks I'm in Europe/Jersey.

/etc/timezone says "Europe/London".

Another vote for "look for /etc/timezone"


Submitted On 30-OCT-2007
Another vote for this bug.  Our bug is that the zoneinfo filesystem scan finds SystemV/PST8PDT before Pacific/Los_Angeles (both files identical), and java removed references to SystemV/PST8PDT as of 2006k (see here: http://java.sun.com/developer/technicalArticles/Intl/FAQ_appendix.html).

So in newer vms, it falls back to a GMT relative zone, and in older ones it uses the deprecated SystemV/PST8PDT file, which doesn't include the 2005 updates to US DST (and which bit us yesterday).  For various reasons we have the older VMs, and our solution was to symlink java's SystemV/PST8PDT file to java's America/Los_Angeles file.  Our original solution was symlinking /etc/localtime, however that's sensitive to rerunning tzselect, which will wipe out the symlink and you're in for more hoary debugging.


Our preferred solutions in order would be:
1. Use /etc/timezone (this would also save an insane but understandable filesystem scan)
2. If a matching file found in the scan is unrecognized or is marked deprecated by the vm, continue scanning.


Submitted On 03-APR-2008
We are experiencing this bug as well on debian etch and debian lenny systems in both 32-bit and 64-bit.  Java is finding SystemV/PST8PDT instead of America/Los_Angeles, and falling back to GMT on a system in Pacific/Honolulu.

Java's time zone detection on linux has evidently always relied on a specific implementation of /etc/localtime as a symlink that was never part of any spec and as it turns out a buggy practice.  Linux has moved beyond that.

This problem has been open over a year and a half.  It affects Sun's latest Java 6 releases.  How can Sun let a problem of this severity remain open on a major OS for so long?


Submitted On 23-APR-2008
grima
To add a bit to this discussion, we are in a similar situation where on some systems java is looking to default to:
  America/Los_Angeles
and on others it is trying:
  posix/America/Los_Angeles

This seems to depend on the order the directories exist on the disk in our /usr/share/zoneinfo directory, i.e. the smallest inode is found first.

One workaround we found was to create a symlink in the jre/lib/zi directory so that the "posix" prefixed string resolves to a path that java can use. This is also a terrible hack, but works.


Submitted On 24-APR-2008
lamont
I left this rant under a related bugID:

...

Reading /etc/sysconfig/clock is completely broken because it may point into file that exist within /usr/share/zoneinfo, but do not exist in Java's internal tzdata structures.  That creates a huge surprise for system administrators where a file that I never in a million years expected java to bother to read is picking up a setting from the system and applying it against a set of files which I never expected /etc/sysconfig/clock to get applied again.  What on earth were you thinking when you thought this was a good idea?

Either keep *all* of your timezone management within the JVM/JDK or keep none of it within the JVM/JDK.  Make it the application developers problem to set the appropriate timezone for the virtual machine and keep timezone files internal to the JDK/JVM which are the application developers problem.  *OR* go ahead and read system configurations like /etc/localtime and even /etc/sysconfig/clock and apply them against the systems tzdata database in /usr/share/zoneinfo.  Pick one.  If my /usr/share/zoneinfo files aren't "Good Enough" for your abstracted away virtual engine then please stay away from my /usr/share/zoneinfo file as well.  Either make time my problem as a system administrator, or make time the application developers problem.  What you've created here is a huge stupid headache.

...

I hadn't come across this bug id and come to understand the full mind-blowingly bizzare implemention of how Java goes and trolls for timezone info out of the system.

Stop doing this to sysadmins.  It is painful.  Please.

Don't do the clever attempt to find something that matches /etc/localtime -- please just fail to startup java with a useful error message about how to set the timezone so that java starts properly.   Starting java in a situation where it does a super-clever "best effort" is just asking for it to fail in this kind of way.  Keep it simple.  Either you can uniquely identify a good timezone or you can't.  If you can't, picking something which is right for half the year and can pass QA tests and then breaks in production when DST rolls around is hugely useless.



Submitted On 27-JUN-2008
simian_vector
This bug is still open?  Are you kidding me?  It's not even hard to fix.  If the file with matching contents doesn't resolve to a valid timezone, go back and try again with a different file.  And honestly, looking for matching file contents is just a brutal hack.

In our first iteration of our production environment (on Debian), we fixed it the same way grima did, by maintaining a symlink in the jre/lib zoneinfo files from the zone it was looking for (SystemV/PST8PDT, which no longer exists in the JRE zoneinfo files) to the one it should have been (America/Los_Angeles).  This is obviously an insane hack to try to maintain over time.

Now it's come up again in our new environment, and I've had to go through and do the research again because it'd been so long since the last instance that I forgot the workflow.  And now the symlink workaround won't work because on one machine the first matching file found is /usr/share/zoneinfo/localtime, the symlink to /etc/localtime (of COURSE it matches! IT'S THE SAME FILE!).  There's no symlink remedy for that, and frankly I'm not sure I'd go with that solution again anyway.  It's just a horrible hack.  We refuse to pass -user.timezone on every VM initialization, which will be a bear to maintain and is incredibly fragile in that it puts the onus on every single app installer to do the job, rather than a single system administrator.

I believe we're going to go with maintaining a /etc/sysconfig/clock file, which is still ridiculous, since it's not a Debian-standard file and will have to be hacked on to every installation, but it's the best of a bad lot until Sun fixes it.


Submitted On 13-AUG-2008
pussinboots
Is it really that hard to read an /etc/localtime file?  If so, it would certainly help if the jvm were to at least print a warning indicating that it is not able to determine the local timezone, suggesting that user set the TZ environment variable...


Submitted On 13-MAR-2009
This bug is still present in 
257 roland> java -version
java version "1.6.0_12"
Java(TM) SE Runtime Environment (build 1.6.0_12-b04)
Java HotSpot(TM) Server VM (build 11.2-b01, mixed mode)

System is Fedora Core 10, local time zone is America/New York.  Fedora is storing the zone in /etc/sysconfig/clock as
    ZONE="America/New York"
which the JVM is translating into GMT-05:00 which is wrong as DST is in effect.  Changing the file content (manually) to 
   ZONE="America/New_York"
"fixes" the problem as far as java is concerned.  I'm still looking for side effects, but the obvious question is that since Java is clearly using that file, why doesn't it try removing spaces from the value as part of its strategy for finding a "correctly" named zone?


Submitted On 10-MAY-2009
Almost all of the suggestions for fixing this bug presented here are bad; the only solution that makes sense is to use system functions to get time information, or if that isn't workable for some unfathomable reason, parse /etc/localtime.

You can find out the system timezone in semi-convenient fashion, using tzset().  This simple program demonstrates:

---- tt.c ----
#include <stdio.h>
#include <time.h>

extern char *tzname[2];
extern long timezone;
extern int daylight;

int main(void)
{
    tzset();
    printf("TZ (standard): %s   TZ (DST): %s\n", tzname[0], tzname[1]);
    printf("Number of seconds west of GMT: %ld\n", timezone);
    printf("Daylight savings in this zone? %s\n", daylight ? "True" : "False");
    printf("Timezone: %s%d%s\n", tzname[0], timezone/3600, tzname[1]);
    return 0;
}

----

$ gcc -o tt tt.c
$ ./tt
TZ (standard): EST   TZ (DST): EDT
Number of seconds west of GMT: 18000
Daylight savings in this zone? True
Timezone: EST5EDT

----

It's astonishing that this bug has been open for almost 3 years.  If the above is for some reason not reliable with weird time zones, see the man page for tzfile(5) on any Linux system to divine the format of /etc/localtime, so you can parse it.  The file has the time zone spelled out in it, along with a specification of the exact start and end of DST, if observed.

Though, I never could figure out why Java should need to know or care about the time zone of the system, beyond what the C libraries already provide...

#include <stdio.h>
#include <time.h>

int main(void)
{
    time_t now;
    struct tm *now2;

    now = time(NULL);
    now2 = localtime(&now);
    /* ctime() returns a string with a '\n' */
    printf("Time:  %s", ctime(&now));
    printf("Zone:  %s\n", now2->tm_zone);
    return 0;
}


$ gcc -o tt2 tt2.c
$ ./tt2
Time:  Mon May 11 01:07:20 2009
Zone:  EDT

The C libraries provide gmtime(), ctime(), and strftime(), which round out what you need to provide any and every combination of time processing.  Java probably never needed anything more complicated than simply wrapping these functions...  


Submitted On 16-DEC-2009
Hi,
Now, I am getting COT Timezone instead of EST Timezone for 
jre version 1.4.2_13. But the issue is quite intermittent. When I installed my Box with Time Zone EST. JRE was populating correct Timezone at the start i.e EST but suddenly it started giving COT till we restart our application (means JVM). I used the standard code to get the TimeZone. Is there any Bug related to this?



PLEASE NOTE: JDK6 is formerly known as Project Mustang