Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
599 views
in Technique[技术] by (71.8m points)

java - Joda time zone different than JDK's

In my client, I have this code:

System.out.println("Java tz: " + TimeZone.getDefault());
System.out.println("Joda tz: " + ISOChronology.getInstance());

These two lines run one after another. I never set time zone or user.timezone manually, just rely on defaults read from the OS & local system.

When executed, they produce:

Java tz: sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
Joda tz: ISOChronology[America/Phoenix]

System time zone is indeed Phoenix, not UTC. How can Joda be correct and JDK be wrong?

EDIT: This is a Windows 7 x64 host, JRE is 1.6.22 x64.

EDIT 2: Don't try to reproduce it. It only fails on some, not all systems (like a few dozen in our 3k user base). I already know Joda checks user.timezone and then TimeZone.getDefault(). So I am looking for an explanation on how can it be different between me calling TimeZone directly and Joda doing it by itself.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When you say "defaults read from the OS & local system", there isn't a single, well-defined place to read this default from. Even the API documentation itself says

Gets the default TimeZone for this host. The source of the default TimeZone may vary with implementation.

So the simple answer is that Joda and your JVM are inferring the default time zone from different sources of information. The point to remember about this is that the default is a guess, not something that the JVM can definitively get access to.

For Sun's 1.5.0_06 JVM on Linux, the following order is used:

  1. Looks to environment variable TZ
  2. Looks for the file /etc/sysconfig/clock and tries to find the "ZONE" entry.
  3. Compares 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.

Joda 1.6.2 uses:

  1. The system property user.timezone.
  2. If the above is null or not a valid identifier, the value of the JDK's TimeZone default is used.
  3. If that fails, UTC is used.

So if you have the above versions of JDK and Joda, I suggest that the user.timezone property may be set in your environment. Other versions may will use other algorithms to acquire the default, though.

Edit: In Sun's JDK 1.6.0_22, the default search first inspects the user.timezone property as well, and if that isn't found it looks up the user.country property in order to get the default value for a country. If neither is set, the default of GMT is used. So the results you observe may well change with your JVM version.


Edit 2: If you've got the source to both (and indeed the sources are both available), then you can simply trace it! Step through the Joda call, to see if it does indeed defer to java.util.TimeZone.getDefault(), and see what the returned value is. Then invoke the JDK method directly and see what you get.

Looking at the JDK sources, it seems that the default timezone is accessed via an inheritable thread local. Thus if someone somewhere calls TimeZone.setDefault(), it may or may not be visible in other threads, depending on whether they've looked up the version already. If you're getting apparently anomalous results from debugging the calls, it could well be simply due to the fact that different threads can have different default TimeZones.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...