Newsletter sign-up
View all newsletters

Sign up for our technology specific newsletters.

Enterprise Java
Email Address:

Set your Java clocks for the new DST

Solutions for adjusting your Java clock during time changes

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone

Page 2 of 2

Keeping the TZDB updated: What are my options?

Consider the following options and solutions:

Do nothing: If your application isn't time and date sensitive and has little interaction with the OS or other services, you might decide that doing nothing is best. Testing beforehand is always advisable (moving the clock backward/forward and analyzing the outcome). Another case where you might choose to take no action is when the new and old DST start/end dates are very close. For example, in Israel in 2006, the outdated JVM DST period ended exactly one hour before the OS DST period. In such a case, you might plan a scheduled system downtime to sleep throughout the problematic one-hour period.

Manually set the user.timezone JVM system property: When the JVM starts, it uses its native libraries to determine the OS time zone and set the user.timezone system correctly. For example, if the OS local time zone is set for Israel, the JVM will set the user.timezone property to Asia/Jerusalem. The Java Calendar and Timezone classes use this property to load the correct default time zone information from the TZDB.

It is also possible to explicitly set the user.timezone property, when running Java, as a geographical/state: java -Duser.timezone=Area/City HelloWorld. Or as a generic time zone expressed in numerical hours "delta" from GMT time, thereby skipping the outdated TZDB, where "delta" is the number of hours prior/ahead of GMT time: java -Duser.timezone=GMT[-+delta] HelloWorld. For example, to set a generic time zone that corresponds to Asia/Jerusalem time without DST, we would use GMT+2, and with DST, we would use GMT=+3.

This method has many drawbacks, including the need to update the startup script for every application twice a year and having to restart the JVM at the exact point in time the DST starts/ends. Also, this is not a viable option for an international application that has to relate to many different time zones.

Upgrade the Java Runtime Environment/JDK version: This is the official recommendation from Sun and BEA. By upgrading to the latest JRE, you are actually replacing your old TZDB with an updated, fresh TZDB.

However, upgrading your JRE might not be such an attractive idea. A typical IT department could have dozens of Java applications; each OS could have many JREs installed on it (figure out which is the one in use and then navigate through seven levels of symbolic links); and, of course, replacing the JRE requires a scheduled application downtime. Another more serious problem is receiving vendor approval for upgrading an application's JVM version. ("We tested the application only with 1.4.1_02! We can't approve 1.4.2_12 without 2 weeks of load testing for memory leaks!" or "We don't support 1.5.0_08! Upgrading will mean warranty is off.") I can't blame the vendors; I've seen applications that have started to crash when launched with '-server' JVM (due to different thread-handling implementations).

Upgrade only the TZDB: Why buy the whole cow when a glass of milk is all you need? This solution is the natural option. Just as we don't upgrade the OS version when we need to update the TZDB, we should just as well not be forced to upgrade the JVM code. According to the long tests I conducted, replacing the TZDB (i.e., the ${JRE_HOME}/lib/zi/ directory) is a legitimate possibility. Read on to see my results.

Test objectives

I wanted to see if the time zone databases of JRE 1.4 and JRE 1.5 matched, so that a TZDB taken from 1.4 could be plugged into 1.5 and vise versa. If so, this would mean I could download the latest JRE version and plug its TZDB into an existing older 1.4/1.5 JRE, thus profiting from updated DST rules without having to pay the warranty/stability/compatibility price of a new JRE version. I also wanted to know if I could update only specific time zone files in the TZDB for an application that only relates to specific local time.

Definitions and axioms:

  1. An updated TZDB: One with DST rules stating that the Asia/Jerusalem DST period ends at 01/10/2006, 02:00 a.m. (jumping back to 01:00 at 02:00). Located at: C:\Program Files\Java\jdk1.5.0_06\jre\lib\zi.
  2. A stale TZDB: One with DST rules stating that the Asia/Jerusalem DST period ends at 01/10/2006, 01:00 a.m. (jumping back to 00:00 at 00:00). Located at: C:\Program Files\Java\j2sdk1.4.0\jre\lib\zi.
  3. An updated JRE: Sun's JDK 1.5.0_06 contains an updated TZDB.
  4. Legacy JRE: JDK 1.4.0 contains a stale TZDB.
  5. Test program: Compares Asia/Jerusalem time zone with an artificial GMT+3, no DST time zone at the critical point in time that tells the updated and stale TZDBs apart.

Test procedure:

  1. Action: Ran the test program using the legacy JRE. Results: Program reports a stale TZDB.
  2. Action: Ran the test program using the updated JRE. Results: Program reports an updated TZDB.
  3. Actions: Replaced the legacy JRE TZDB with the updated TZDB (copy "…\jdk1.5.0_06\jre\lib\zi" directory over "…\j2sdk1.4.0\jre\lib\zi"), ran the test program using the legacy JRE. Results: Program reports an updated TZDB.
  4. Actions: Restored all JREs to their original TZDBs, replaced the updated JRE TZDB using the legacy JRE TZDB, ran the test program using the updated JRE. Results: Program reports a stale TZDB.
  5. Action: Same as Steps 3-4, but updated only the "…\zi\Asia\Jerusalem" file and not the entire TZDB. Results were identical.

After running the above test steps on an ad hoc piece of software I wrote, I tested it on an existing OLTP (Online Transaction Processing) Web application test environment, later to be applied to all of the company production application servers.

Conclusions

I conducted more tests, not documented here, that further showed replacing the TZDB (i.e., the ${JRE_HOME}/lib/zi/ directory) as a legitimate possibility for solving our DST issue. The TZDB is fully compatible between all 1.4.X and 1.5.X versions, and also platform independent. It's probably safer to stop the JVM while you are downloading it, although theoretically, you might presume that it shouldn't get in the JVM's way unless a classloader was in the middle of a Timezone classloading operation.

This option is much less intrusive than the JRE upgrade option since only new, trivial data, and not new untested code, is introduced into your delicate, high-availability, demanding application. You might have an easer task convincing your application vendor to approve with the TZDB upgrade.

This solution isn't an option for IBM 1.4.X and Java 1.3.x versions that don't have an external TZDB; you should go with a JRE upgrade.

Another option is to switch over to Joda-Time, an easy-to-use open source Java date and time API that provides a quality replacement for the Java date and time classes. The design allows for multiple calendar systems, while still providing a simple API. In addition to the Gregorian Calendar, the Julian, Buddhist, Coptic, and Ethiopic systems are also included. It also claims to have better performance characteristics then the vanilla Java.util date and time. It also features a separate TZDB that can be updated as needed, thus further decoupling the JRE and TZDB.

Fixing the time warp

What can be done to overcome the stale DST rules problem? How can Java change and grow to overcome this maintenance issue?

Should every programming and scripting platform implement and maintain its own TZDB? I sure don't think so. The OS has its own TZDB. I believe the JVM, being a native OS component as it is, should be allowed to utilize the existing OS TZDB (this option could be switch on/off via a special -X startup argument). Some platforms like mobile phones or other devices might not have an internal updated TZDB. But true mission-critical applications run on standard operating systems, and Sun should provide them with precedence. Regardless, this solution should only be an option, not mandatory.

A TZDB update utility could be provided: just auto download only the TZDB without the JRE and utilize existing update mechanisms like JavaUpdate in Windows or RPM/up2date/yum in Linux. Or a way to hot deploy a TZDB into the JVM could be offered, either through a classloader reloading or through specially crafted logic. I hope this functionality could be included in future versions of Java.

I believe that alongside the original JRE/JDK 1.3.x_y versions, Sun should provide the same JRE/JDK 1.3.x_y version with an up-to-date TZDB. That way, we could update a production environment without introducing new code into the ecosystem. (Note: In 1.3, the TZDB is indeed hard-coded into the code, but it is concentrated in a specific area. Thus, changing it won't really introduce new code.) Sun should provide a way to overcome the 1.3 TZDB design compromise while keeping production environments free of new code.

About the author

Gili Nachum works as a senior software architect at db@net, a company that provides IT architecture solutions and services. Nachum has been writing software since 1996 and programming in Java since 2000. Nahum holds a bachelor's degree in economics and administration, lives in Israel, and specializes in RTS computer games.
  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comment
Login
Forgot your account info?
Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources