Java TimeZone 和 Linux TimeZone問題

昨天發現跑在Linux上的java程序獲取的默認時區有問題。php

因爲我所用Linux的時區由/etc/localtime所指的文件(若是環境變量TZ不存在時):
[xx:~]> ls -l /etc/localtime
lrwxrwxrwx  1 root root 18 Jun 21  2008 /etc/localtime -> /var/etc/localtime
[xx:~]> ls -l /var/etc/localtime
lrwxrwxrwx  1 root root 30 May 14 09:46 /var/etc/localtime -> /usr/share/zoneinfo/US/Easternhtml

開始時,我覺得應該是和/etc/localtime指向的時區同樣的,接着才發現原來java在沒有TZ環境變量時取的是 /etc/sysconfig/clockjava

中的時時區。 Sun上面有和我這種狀況相關的bug - Default timezone is incorrectly set occasionally on Linux(http://bugs.sun.com/view_bug.do?bug_id=6456628), 裏面描述了java vm取的默認timezone的算法:linux

1)若有環境變量 TZ設置,則用TZ中設置的時區算法

2)在 /etc/sysconfig/clock文件中找 "ZONE"的值vim

3)如何2)都沒,就用/etc/localtime 和 /usr/share/zoneinfo 下的時區文件進行匹配,如找到匹配的,就返回對應的路徑和文件名。
測試

 

下面是個人測試:spa

java測試程序(來自:http://www.minaret.biz/tips/timezone.html)code

import java.util.Date;
import java.util.TimeZone;

public class TimeTest {

public static void main(String args[]) {
long time = System.currentTimeMillis();
String millis = Long.toString(time);
Date date = new Date(time);
System.out.println("Current time in milliseconds = " + millis + " => " + date.toString());
System.out.println("Current time zone: " + TimeZone.getDefault().getID());
}
}

 

查看本地時區設置:htm

[xx:~]> echo $TZ

(TZ 環境變量沒設置)
[xx:~]> ls -l  /var/etc/localtime
lrwxrwxrwx  1 root root 30 May 14 02:24 /var/etc/localtime -> /usr/share/zoneinfo/US/Arizona

[xx:~]>date
Fri May 14 02:30:05 MST 2010

date 命令顯示的時間 和 /var/etc/localtime 指向的時間一致

查看/etc/sysconfig/clock中的時區設置(Redhat Linux)
[xx:~]> cat /etc/sysconfig/clock
ZONE="America/New_York"
UTC=false
ARC=false

[xx:~]> java TimeTest
Current time in milliseconds = 1273829564349 => Fri May 14 05:32:44 EDT 2010
Current time zone: America/New_York
Current time zone display: Eastern Standard Time
[xx:~]>

TimeTest運行結果顯示,java vm取得的的默認時區和 /etc/sysconfig/clock 中的設置同樣。讓咱們來驗證一下:
1)修改/etc/sysconfig/clock:
[xx:~]> vim /etc/sysconfig/clock
ZONE="US/Central"
UTC=false
ARC=false
2)再運行 TimeTest
[xx:~]> java TimeTest
Current time in milliseconds = 1273829718269 => Fri May 14 04:35:18 CDT 2010
Current time zone: US/Central
Current time zone display: Central Standard Time


修改/var/etc/localtime 指向時區
先看看date顯示:
[xx:~]> date
Fri May 14 02:36:37 MST 2010
[xx:~]> sudo ln -sf /usr/share/zoneinfo/US/Central  /var/etc/localtime
查看date命令結果的變化
[xx:~]> date
Fri May 14 04:37:41 CDT 2010
能夠到時間和時區自動變了


好,再看另一種狀況:當 TZ 這個環境變量存在並有設置時

首先看看TZ的值爲空時,date命令結果的變化
[xx:~]> export TZ=
[xx:~]> date
Fri May 14 09:41:04 UTC 2010

時間變了,且時區顯示是UTC(Universial Time Coordination).

也看看TimeTest的運行結果:
[xx:~]> java TimeTest
Current time in milliseconds = 1273830175690 => Fri May 14 09:42:55 GMT 2010
Current time zone: GMT
Current time zone display: Greenwich Mean Time
[xx:~]>

能夠看出,java vm 默認時區是GMT。

給TZ賦某個時區:

[xx:~]> export TZ="US/Central"
[xx:~]> date

Fri May 14 04:44:40 CDT 2010 

date的輸出跟着 TZ 變量立刻調整過來

運行TimeTest
[xx:~]> java TimeTest
Current time in milliseconds = 1273830328966 => Fri May 14 04:45:28 CDT 2010
Current time zone: US/Central
Current time zone display: Central Standard Time

TimeTest 取得和TZ同樣的時區


[xx:~]> sudo ln -sf /usr/share/zoneinfo/US/Eastern /var/etc/localtime
[xx:~]> date
Fri May 14 04:46:16 CDT 201

[xx:~]> export TZ="US/Eastern"
[xx:~]> date
Fri May 14 05:47:58 EDT 2010

 

參考資料:

1.Default timezone is incorrectly set occasionally on Linux
http://bugs.sun.com/view_bug.do?bug_id=6456628

2. 如何設置Linux時間http://www.hypexr.org/linux_date_time_help.php3. 解決java default Timezone 問題的方法http://www.minaret.biz/tips/timezone.html

相關文章
相關標籤/搜索