Java の TimeZone

先日 Java の Web アプリでログに出力される時間が UTC で出力されるという事がありました。日本に住んでいるので JST で表示されないと紛らわしくて困ります。
すぐに思いついたのが /etc/localtime が UTC に対応するものになっていることでしたが、違いました。ちゃんと Asia/Tokyo に対応するものになっており date コマンドの出力も JST で表示されます。次に疑ったのは環境変数です。しかし、/proc/<pid>/environ を見ても TZ などが設定されてはいません。ためしに TZ を設定して起動すると、意図通りログに出力される時間は JST で出力されています。とりあえずこれで直ると言えば直るのですが、どうも気になりますし、気持ち悪いです。

Web を検索していくつかのページを見て見ましたが、出てくるのは /etc/localtime や環境変数と Java のシステムプロパティ user.timezone のことだけです。

まずは検証用の簡単なコードを書きました。

問題のあるサーバ上でこれを実行すると以下の結果を得ました。

次に、問題のないサーバで実行すると以下の結果を得ました。

いずれのサーバでも /etc/timezone は Asia/Tokyo になっていますし、環境変数やシステムプロパティも設定していません。

何か OS の設定が関係していると仮定し /etc 以下を探してみると…、ありました。/etc/timezone です。問題のあるサーバにはこのファイルがあり、内容は Etc/UTC になっていました。問題のないサーバではこのファイルはありませんでした。早速ファイルの内容を Asia/Tokyo に書き換えて検証コードを実行すると、

ビンゴです。

気になったので /etc/timezone の内容は Asia/Tokyo のままにして /etc/localtime を UTC を指すようにして実行してみると

予想通り /etc/localtime よりも /etc/timezone の方が優先されるようです。

この /etc/timezone は debian 系の Ubuntu にはありましたが Red Hat 系の CentOS や Scientific Linux には確認した限りではありませんでした。ちなみに Red Hat 系のディストリビューションでも /etc/timezone を作ってやるとそちらが優先されました。

今回の検証は Ubuntu 12.04 及び Scientific Linux 6.4 上で行いました。
java.util.TimeZone では最終的に native メソッドを呼んでいるため他の環境では結果が異なるかもしれません。

Both comments and trackbacks are currently closed.