This chapter describes some issues that can arise with time zone settings with the Java Runtime Environment (JRE) on the Windows operating system. It also describes troubleshooting techniques and workarounds to solve these issues.
This chapter contains the following sections:
The JRE reads the native time zone information to determine your default time zone. For example, on Windows, the JRE queries the registry to determine the default time zone.
However, the JRE also maintains its own time zone database. This provides cross-platform support because the different operating system APIs are not sufficient to support the Java APIs. The Java time zone database supports time zone IDs and determines daylight saving time rules for all the time zones that the JRE supports. The Java time zone database can be found in <install_dir>/jre/lib/zi
. The tzupdater
tool is available to update the Java time zone database.
Modifications to the JRE for each specific operating system are necessary so that the operating system can deliver the system time to the JRE. Then, if a Java application requests the system date by calling date and time related constructors, the system time is returned.
Examples of such constructors are:
java.util.Date()
java.util.GregorianCalendar()
Constructors related to date and time include:
System.currentTimeMillis()
System.nanoTime()
Operating system-specific patches might be required to ensure that the correct system time is delivered to the JRE.
The time zone database version that ships in any JRE from Oracle is documented in the Release Notes. However, the actual version can be different from the version mentioned there if the JRE has been patched using the tzupdater
tool.
To determine the current time zone data version of your JRE either run the tzupdater
tool with the Version option, or examine the header of the ZoneInfoMappings
file.
The Java time zone updater tool is called tzupdater
. To determine the time zone database version of your JRE, run this tool as follows:
java -jar tzupdater.jar -V
Here is a typical output from running the tzupdater
tool.
tzupdater version 1.3.33-b01JRE time zone data version: tzdata2010iEmbedded time zone data version: tzdata2010l
You can download the tzupdater
tool from this web page: http://www.oracle.com/technetwork/java/javase/tzupdater-readme-136440.html
Even without the tzupdater
tool, you can quickly check the version by examining the header of the file <java-home>/lib/zi/ZoneInfoMappings
. This data is stored in a binary format that is specific to Java. On Linux, Solaris, and Mac OS X operating systems, you can use the octal dump command to see the header of this file. Here is the octal dump command format:
/usr/bin/od -c -j 11 -N 11 <java-home>/lib/zi/ZoneInfoMappings
Here is a typical result of such a dump command:
/usr/bin/od -c -j 11 -N 11 /farfaraway/jdks/jdk1.6.0_21/jre/lib/zi/ZoneInfoMappings0000000 t z d a t a 2 0 1 0 i0000013
In this example the time zone data version that is embedded in that JRE is tzdata2010i
.
On Microsoft Windows, you can use the findstr
command to examine the ZoneInfoMappings
file. Here is an example.
findstr tzdata <java-home>\lib\zi\ZoneInfoMappings
Sometimes when you run tzupdater
it quits with the message: There's no tzdata available for this Java runtime. Here are two examples.
$ java -jar tzupdater.jar -Vtzupdater version 1.3.39-b01JRE time zone data version: tzdata2009iThere's no tzdata available for this Java runtime.
$ java -jar tzupdater.jar -u There's no tzdata available for this Java runtime.
The likely cause is that you are using a JRE that is not from Oracle. Oracle provides the JRE for Solaris (x86, x64, SPARC), Linux (x86, x64, ARM), Microsoft Windows (x86, x64), and Mac OS X (x64). The java.vendor
property value for these is Sun Microsystems Inc., Oracle Corporation or BEA Systems, Inc. Oracle does not provide the JRE for other platforms.
The output of running the java -version
command does not provide enough information to determine the actual vendor of a JRE. However, running tzupdater
in update mode with the -v
option does print out the java.vendor
property. Here is an example of attempting to run tzupdater when the environment is HP_UX from Hewlett Packard.
root@my_server:/opt/java6/bin> uname -a HP-UX my_server B.11.23 U ia64 1114591084 unlimited-user license root@my_server:/opt/java6/bin> ./java -version java version "1.6.0.05" Java(TM) SE Runtime Environment (build 1.6.0.05-jinteg_14_oct_2009_01_44-b00) Java HotSpot(TM) Server VM (build 14.2-b01-jre1.6.0.05-rc5, mixed mode) root@my_server:/opt/java6/bin> ./java -jar tzupdater.jar -v -u java.home: /opt/java6/jre java.vendor: Hewlett-Packard Co. java.version: 1.6.0.05 JRE time zone data version: tzdata2009i There's no tzdata available for this Java runtime.
In this example, java.vendor
is set to Hewlett-Packard Co. The JRE that you are trying to update using tzupdater
is not supported by Oracle.
A possible solution is visit the website of your JRE vendor and determine whether a time zone updater tool is available there. For example, the Hewlett-Packard version of the tzupdater tool is available at this URL:
http://h18012.www1.hp.com/java/DST/ivms/README.html
This section clarifies how the JRE determines the default time zone on the Windows Vista and Windows 7 operating systems. If Java doesn't report the expected time zone, use the troubleshooting techniques provided in the following sections:
Check which time zone the JRE reports as default
Determine the time zone setting in the Control Panel
Check whether automatic daylight saving time adjustment is enabled
Check whether you can use -Duser.timezone
Use the tzutil.exe tool in Windows 7
You can write a simple program to determine which time zone the JRE reports as the default time zone, based on a check with the native operating system.
The Java program in Example 7-1 returns the default time zone:
Example 7-1 Java Code Snippet to Check the Time Zone Setting in the JRE
public class DefaultTimeZone { public static void main(String[] args) { System.out.println(java.util.TimeZone.getDefault().getID()); } }
You can save the code snippet in Example 7-1 to a file named DefaultTimeZone.java
and compile it using the javac
command. Then you can run the compiled DefaultTimeZone
class, as shown in Example 7-2.
Example 7-2 Compiling and Running the DefaultTimeZone Program
c:\tztest> javac DefaultTimeZone.java c:\tztest> java DefaultTimeZone Europe/Berlin
In Example 7-2, the default time zone is Europe/Berlin. Running the program should display your local time zone. If the output is not the expected time zone, then continue with the following troubleshooting steps.
You can change or examine the system's default time zone using the Windows Control Panel. For example, you can select this time zone setting in Windows 7:
(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
The corresponding value for the Registry key TimeZoneKeyName
is W. Europe Standard Time.
You can check whether automatic adjustment of daylight saving time is enabled through the graphical user interface (GUI) or through the Windows registry.
To use the Control Panel to check whether automatic adjustment of daylight saving time is enabled, follow these steps.
Click the Windows Start button and then click Control Panel.
Click Date and Time.
Click the Change Time Zone button.
There is a click box labeled Automatically adjust time for Daylight Savings Time. Observe whether or not this click box is clicked, and change the setting if you desire.
Click OK. This returns you to the Date and Time dialog box.
You can run Windows Registry Editor to check whether automatic adjustment of daylight saving time is enabled.
Caution: It is a good practice to back up the Windows registry before examining or editing it. If you make a mistake in editing, you can damage the Windows registry. |
To enable automatic adjustment of daylight saving time from the Windows registry:
Click the Windows Start button.
In the Search programs and files field, type regedit and then press Enter to open the Registry Editor.
In the Registry Editor, search for the key DynamicDaylightTimeDisabled and examine the setting.
If the registry setting is 1, then dynamic daylight time is disabled.
If the registry setting is 0, then dynamic daylight time is enabled.
If you prefer, you can access the Windows registry from the Windows command window.
In Example 7-3, the registry setting is 1. With this setting, the clock is not automatically adjusted for daylight saving time.
Example 7-3 DynamicDaylightTimeDisabled Registry Key Set to True
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation] "DynamicDaylightTimeDisabled"=dword:00000001
If you have disabled the DynamicDaylightTimeDisabled
option, then Java always returns a GMT (Greenwich mean time) offset and not a time zone ID that is compatible with the uniform naming convention (such as Europe/Berlin). For example, the offset will be expressed as GMT+01 and not Europe/Berlin.
You can change or examine the system's default time zone by using the Windows Control Panel.
To set the system's default time zone from the Control Panel:
Click the Windows Start button and then click Control Panel.
Click Date and Time.
Click the Change Time Zone button.
From the Time Zone menu, select your preferred time zone.
Click OK. This returns you to the Date and Time dialog box.
Click OK to close the Date and Time dialog box.
For example, you can select this time zone in Windows 7:
(UTC)+1:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna.
The corresponding value for the Registry key TimeZoneKeyName
is W. Europe Standard Time.
You can explicitly set a default time zone on the command line by using the Java system property called user.timezone
. This bypasses the settings in the Windows operating system and can be a workaround in some cases. For instance, this setting is useful if you want DST (daylight saving time) only for a single Java program running on the system.
The following example examines the system property -Duser.timezone by running a Java program called DefaultTimeTestZone from the Windows Command Prompt window.
c:\tztest> java -Duser.timezone=America/New_York DefaultTimeZone
America/New_York
If setting a default time zone explicitly by specifying -Duser.timezone
works for the DefaultTimeTestZone
program, but does not work for your program, you should check whether your code overwrites the default Java time zone during runtime, with a method call such as this:
TimeZone.setDefault(TimeZone zone)
With Windows 7, a tool called tzutil.exe
is available. With this tool, you can request the current time zone ID abbreviation without manually reading the registry.
Here is an example of running tzutil.exe
. The first line is the command that you enter in Windows Command Prompt window. The second line is the system response.
tzutil /g W. Europe Standard Time
On Windows, the JRE uses a file <java-home>\lib\tzmappings
to represent the mapping between Windows and Java time zones. Each line in the file has four tokens. The first token is the Windows time zone registry key called TimeZoneKeyName
. (See Determine the Setting in the Control Panel)
The second token is a time zone map ID. (This is not used in Windows Vista and Windows 7.) The third token is the locale. The fourth token represents the Java time zone ID. The important tokens are token number one, number three (which can be empty), and number four. (Note that this file is not a public interface.)
If you select the time zone called (UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna in the Windows Control Panel, then the relevant line in the file tzmappings
is:
W. Europe Standard Time:2,3::Europe/Berlin:
In this example, the JRE recognizes your default time zone (token number four) as Europe/Berlin.
If there is no appropriate mapping entry in the tzmappings file, then it is possible that Microsoft introduced a new time zone in a Windows update, and that the new time zone is not available to the JRE. In this situation, you can file a bug report for the JRE and request a new entry in the tzmappings file from the following URL:
http://bugs.sun.com
A similar disconnect between the operating system and the JRE is possible if you have run the tool tzedit.exe.
This tool is posted by Microsoft on the Internet, and allows users to add new time zones. The JRE is unlikely to have a time zone introduced into the system by this tool. Again, the solution is to file a bug to request that a new entry be added to the tzmappings
file.