9 JREでのタイムゾーン設定

この章では、Windowsオペレーティング・システムでJava Runtime Environment (JRE)のタイムゾーン設定に関連して発生する可能性のあるいくつかの問題について説明します。さらに、これらの問題を解決するためのトラブルシューティング方法および回避方法についても説明します。

この章の構成は、次のとおりです。

ネイティブ・タイムゾーン情報およびJRE

Java Runtime Environment (JRE)では、デフォルト・タイムゾーンを判別するためにネイティブ・タイムゾーン情報を読み取ります。

たとえば、Windowsでは、JREはデフォルト・タイムゾーンを判別するためにレジストリを問い合わせます。

しかし、JREでは独自のタイムゾーン・データベースも保持しています。これにはクロスプラットフォーム・サポートが備わっていますが、その理由は様々なオペレーティング・システムのAPIがJava APIをサポートするのに不十分であるからです。Javaタイムゾーン・データベースは、タイムゾーンIDをサポートし、JREがサポートしているすべてのタイムゾーンの夏時間ルールを決めます。tzupdaterツールは、Java SEダウンロード・ページからダウンロードして使用できます。

オペレーティング・システムがシステム時間をJREに配信できるように、JREへの変更をオペレーティング・システムごとに行う必要があります。その後、Javaアプリケーションが日付と時間に関連したコンストラクタを呼び出してシステム日付を要求すると、システム時間が返されます。

そのようなコンストラクタの例を次に示します。

  • java.util.Date()
  • java.util.GregorianCalendar()

日付と時間に関連したコンストラクタには、次が含まれています。

  • System.currentTimeMillis()
  • System.nanoTime()

正しいシステム時間が必ずJREに配信されるようにするには、オペレーティング・システム固有のパッチが必要になる場合があります。

次の項では、タイムゾーンの設定のトラブルシューティング手法について説明します。

使用中のタイムゾーン・データ・バージョンの判別

Oracle提供のJavaランタイムに付属しているタイムゾーン・データベースのバージョンは、リリース・ノートに記載されています。ただし、tzupdaterと呼ばれるJavaタイムゾーン更新ツールを使用してJavaランタイムにパッチを適用した場合は、実際のバージョンがそこに記載されているバージョンと異なることがあります。

tzupdaterツールを使用してJavaランタイムの現在のタイムゾーン・データ・バージョンを判別するには、次の例に示すように-Vオプションを指定してツールを実行します:

java -jar tzupdater.jar -V

tzupdaterツールの実行による標準的な出力を次に示します。

tzupdater version 2.2.0-b01
JRE tzdata version: tzdata2018g

tzupdaterツールは、Timezone Updater ToolというWebページからダウンロードできます。

Javaタイムゾーン更新ツールの問題のトラブルシューティング

tzupdaterの実行時に、それが「このJavaランタイムで使用できるタイムゾーン・データはありません」というメッセージを表示して終了することがときどきあります。次に2つの例を示します。

$ java -jar tzupdater.jar -V 
tzupdater version 2.1.1-b01 
JRE tzdata version: tzdata2017b
There's no tzdata available for this Java runtime.

考えられる原因は、OracleのものではないJavaランタイムを使用していることです。Oracleは、Linux (x64)、Microsoft Windows (x64)およびmacOS (x64)用のJavaランタイムを提供しています。Oracleでは、それ以外のプラットフォーム用のJavaランタイムを提供していません。

java -versionコマンドを実行した場合の出力は、Javaランタイムの実際のベンダーを判断するのに十分な情報を提供しません。しかし、-vオプションを指定してtzupdaterを更新モードで実行すると、java.vendorプロパティが出力されます。次の例に、環境がHewlett PackardのHP_UXである場合のtzupdaterの実行結果を示します。

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 -l
java.home: /opt/java6/jre
java.vendor: Hewlett-Packard Co.
java.version: 1.6.0.05
JRE tzdata version: tzdata2009i
There's no tzdata available for this Java runtime.

前の例では、java.vendorが「Hewlett-Packard Co.」に設定されています。tzupdaterを使用して更新を試みているJavaランタイムはOracleでサポートされていません。

考えられる解決方法は、使用しているJavaランタイム・ベンダーのWebサイトを参照して、使用可能なタイムゾーン更新ツールがあるかどうかを確認することです。

Windowsでのデフォルト・タイムゾーンの判別

このセクションでは、Windows 10以降のオペレーティング・システムでJavaランタイムがデフォルト・タイムゾーンを判別する方法について明確に説明します。期待されたタイムゾーンが報告されない場合は、次の各セクションで説明するトラブルシューティング方法を使用してください。

Javaランタイムが報告するデフォルト・タイムゾーンの確認

ネイティブ・オペレーティング・システムによるチェックに基づいて、JDKがデフォルト・タイムゾーンとして報告するタイムゾーンを確認するための簡単なプログラムを作成できます。

次の例のJavaプログラムはデフォルト・タイムゾーンを返します。

public class DefaultTimeZone {
    public static void main(String[] args) {
        System.out.println(java.util.TimeZone.getDefault().getID());
    }
}

前の例のコード・スニペットをDefaultTimeZone.javaという名前のファイルに保存し、javacコマンドを使用してコンパイルできます。次に、次の例に示すように、コンパイルしたDefaultTimeZoneクラスを実行できます。

c:\tztest> javac DefaultTimeZone.java
c:\tztest> java DefaultTimeZone
Europe/Berlin

前の例では、デフォルト・タイムゾーンはEurope/Berlinです。プログラムを実行すると、ローカル・タイムゾーンが表示されるはずです。出力が予期されたタイムゾーンでない場合は、次のトラブルシューティング・ステップを続けて実行してください。

コントロール・パネルでの設定の確認

Windows設定またはWindowsコントロール・パネルを使用して、システムのデフォルト・タイムゾーンを変更または確認できます。たとえば、Windows 10で次のタイムゾーン設定を選択できます。

(UTC+01:00)アムステルダム、ベルリン、ベルン、ローマ、ストックホルム、ウィーン

対応するTimeZoneKeyNameレジストリ・キーの値は、西ヨーロッパ標準時間です。

夏時間の自動調整の確認

グラフィカル・ユーザー・インタフェース(GUI)またはWindowsレジストリを通じて、夏時間の自動調整が有効かどうかを確認できます。

  • GUIによる方法: コントロール パネルを使用して夏時間の自動調整が有効かどうかを確認するには:

    1. Windowsの「スタート」ボタン、「コントロール パネル」の順にクリックします。

    2. 日付と時刻」をクリックします。

    3. タイム ゾーンの変更」ボタンをクリックします。

    4. 「自動的に夏時間の調整をする」というラベルの付いたチェック・ボックスが表示されます。このチェック・ボックスが選択されているかどうかを確認し、必要に応じて設定を変更します。

    5. 「OK」をクリックします。「日付と時刻」ダイアログ・ボックスに戻ります。

  • Windowsレジストリによる方法: Windowsレジストリ・エディタを実行して夏時間の自動調整が有効かどうかを確認できます。

    ノート:

    Windowsレジストリを確認または編集する前にバックアップを取っておくことをお薦めします。間違った操作をすると、Windowsレジストリが損なわれる可能性があります。

    Windowsレジストリから夏時間の自動調整を有効にするには:

    1. Windowsの「スタート」ボタンをクリックします。

    2. 「プログラムとファイルの検索」フィールドで、「regedit」と入力してから[Enter]キーを押して、レジストリ・エディタを開きます。

    3. レジストリ・エディタで、DynamicDaylightTimeDisabledというキーを探し、その設定を調べます。

      レジストリ設定が1の場合、動的な夏時間は無効になっています。

      レジストリ設定が0の場合、動的な夏時間は有効になっています。

    お好みで、Windowsコマンド・ウィンドウからWindowsレジストリにアクセスすることもできます。

次の例では、レジストリ設定は1です。この設定では、時計は夏時間に合わせて自動的に調整されません。

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation]
"DynamicDaylightTimeDisabled"=dword:00000001

DynamicDaylightTimeDisabledオプションを無効にした場合、JavaはGMT (グリニッチ標準時間)オフセットを返し、統一されたネーミング規則と互換性のあるタイムゾーンID (「Europe/Berlin」など)を返しません。たとえば、このオフセットは「Europe/Berlin」ではなくGMT+01として表されます。

Windows設定でのデフォルト・タイムゾーンの設定

Windows設定を使用して、システムのデフォルト・タイムゾーンを変更または確認できます。

Windows設定からシステムのデフォルト・タイムゾーンを設定するには:

  1. Windowsの「スタート」ボタンをクリックします。
  2. 「設定」をクリックします。
  3. 「時刻と言語」をクリックします。
  4. 「タイム ゾーン」ドロップダウン・リストから、希望するタイムゾーンを選択します。

たとえば、Windows 10で次のタイムゾーンを選択できます。

(UTC)+1:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna.

対応するTimeZoneKeyNameレジストリ・キーの値は、西ヨーロッパ標準時間です。

-Duser.timezoneシステム・プロパティの確認

user.timezoneと呼ばれるJavaシステム・プロパティを使用することにより、コマンド行でデフォルト・タイムゾーンを明示的に設定できます。これにより、Windowsオペレーティング・システムでの設定が省略され、回避方法となることもあります。たとえば、システム上で実行されている1つのJavaプログラムでのみ夏時間(DST)を適用する場合にこの設定が役立ちます。

次の例は、システム・プロパティ-Duser.timezoneを示しています。「Javaランタイムが報告するデフォルト・タイムゾーンの確認」で説明されているDefaultTimeTestZone.javaプログラムを、Windowsコマンド・プロンプト・ウィンドウでコンパイルします。次のコマンドを実行します。

c:\tztest> java -Duser.timezone=America/New_York DefaultTimeTestZone America/New_York

-Duser.timezoneを指定することでデフォルト・タイムゾーンを明示的に設定することがDefaultTimeTestZoneプログラムには有効だが、使用しているプログラムには有効でない場合、実行時に次のようなメソッド呼出しを使用してコードがデフォルトのJavaタイムゾーンを上書きするかどうかを確認するようにしてください。

TimeZone.setDefault(TimeZone zone)

Windowsの特別なツール

Windowsオペレーティング・システムには、tzutil.exeというツールがあります。このツールを使用すると、手動でレジストリを確認することなく、現在のタイムゾーンIDの略称を要求できます。

tzutil.exeの実行例を次に示します。最初の行は、Windowsの「コマンド プロンプト」ウィンドウで入力するコマンドです。2番目の行はシステム・レスポンスです。

tzutil /g

W. Europe Standard Time

タイムゾーン・マッピングの内部表現

Windowsでは、Javaランタイムは<java-home>\lib\tzmappingsファイルを使用してWindowsタイムゾーンとJavaタイムゾーンのマッピングを表現します。このファイルの各行には3つのトークンがあります。最初のトークンは、TimeZoneKeyNameと呼ばれるWindowsタイムゾーンのレジストリ・キーです。「コントロール・パネルでの設定の確認」を参照してください。

2番目のトークンは国コードまたはデフォルト・コード001で、UN M49コードは「World」を意味します。3番目のトークンはJavaタイムゾーンIDを表しています。

Windowsのコントロール・パネルで「(UTC+01:00)アムステルダム、ベルリン、ベルン、ローマ、ストックホルム、ウィーン」と呼ばれるタイムゾーンを選択した場合、tzmappingsファイルの関連する行は次のようになります。

W. Europe Standard Time:AD:Europe/Andorra:
W. Europe Standard Time:AT:Europe/Vienna:
W. Europe Standard Time:CH:Europe/Zurich:
W. Europe Standard Time:DE:Europe/Berlin:
W. Europe Standard Time:GI:Europe/Gibraltar:
W. Europe Standard Time:IT:Europe/Rome:
W. Europe Standard Time:LI:Europe/Vaduz:
W. Europe Standard Time:LU:Europe/Luxembourg:
W. Europe Standard Time:MC:Europe/Monaco:
W. Europe Standard Time:MT:Europe/Malta:
W. Europe Standard Time:NL:Europe/Amsterdam:
W. Europe Standard Time:NO:Europe/Oslo:
W. Europe Standard Time:SE:Europe/Stockholm:
W. Europe Standard Time:SJ:Arctic/Longyearbyen:
W. Europe Standard Time:SM:Europe/San_Marino:
W. Europe Standard Time:VA:Europe/Vatican:
W. Europe Standard Time:001:Europe/Berlin:

この例では、Javaランタイムはユーザーの国に基づいてデフォルトのタイムゾーン(トークン番号3)を認識します。たとえば、国コードがADの場合、デフォルトのタイムゾーンは「ヨーロッパ/アンドラ」です。

tzmappingsファイルに適切なマッピング・エントリが存在しない場合、MicrosoftがWindows Updateで新しいタイムゾーンを導入したが、その新しいタイムゾーンがJavaランタイムで使用できない可能性があります。この場合、バグ・レポートを提出し、オラクルのJavaバグWebサイトからtzmappingsファイルの新しいエントリを要求できます。

tzedit.exeツールを実行すると、オペレーティング・システムとJavaランタイムの間で同様の切断が発生する可能性があります。このツールはMicrosoftによって提供されており、ユーザーが新しいタイムゾーンを追加できます。Javaランタイムで、このツールによってタイムゾーンがシステムに導入される可能性は高くありません。この場合も、解決方法はバグを提出して、新しいエントリがtzmappingsファイルに追加されるように要求することです。