Page 2 of 2
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.
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.
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.
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.
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.
Archived Discussions (Read only)