チョーひさびさに投稿。あまりに驚いてムカついたため。
Javaで構築されたシステムをAmazon LinuxからAmazon Linux 2に移行する作業をしていたときに発覚。
Amazon Linux 2ではシステムのタイムゾーンを設定するため、以下のコマンドを実行する。
#timedatectl set-timezone "Asia/Tokyo"
通常はこれで全てOKのはずで、ネットを検索してもAmazon Linux 2やCentOS7系の記事ではココマデしか書かれていません。
しかし、Javaのプログラム内ではTimeZoneは正しく取得出来ずに、UTCになります。
サンプル:
TimeZoneInfo.java
import java.util.Calendar;
class TimeZoneInfo {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
System.out.println(cal.getTimeZone());
System.out.println(System.getProperty("user.timezone"));
}
}
実行結果:
sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
UTC
対応方法はいくつかあります。(見つけるのにすげぇ時間かかった)
- 環境変数TZ=Asia/Tokyoを設定する
- javaのコマンドラインに
-Duser.timezone=Asia/Tokyo
を付ける - Amazon Linuxの頃の定石の設定方法だった
/etc/sysconfig/clock
の修正を実施する
などなど。
問題点はいくつかあるのだと思う。
- timedatectlでは
/etc/localtime
は書き換えてくれるが、/etc/sysconfig/clock
は書き換えてくれない。(そもそもCentOS7だとファイル自体がないらしい・・・・) - Javaは
/etc/localtime
を見てくれない。バージョンによって違うらしい。glibcの挙動の変化かもしれないが、詳細な原因は分からない。 - systemd系になって/etc/sysconfigはあまり参照されなくなったが、過去の遺産は残っているので、互換性にもう少し考慮してくれ。。。。
- 旧システムはJava1.6で実行、新システムはJava7で実行。Java8以降の最新だとどうなってるのかは知らん。
どれが一番正しい(やるべき)対応方法なのだらう。。。。
というかTimeZoneの設定くらいなんとか標準化してくれ。