AtlasHR 2012-04-16
JavaTimeZone和LinuxTimeZone问题
1人收藏此文章,我要收藏发表于1年前,已有1777次阅读共0个评论
昨天发现跑在Linux上的java程序获取的默认时区有问题。
由于我所用Linux的时区由/etc/localtime所指的文件(如果环境变量TZ不存在时):
[xx:~]>ls-l/etc/localtime
lrwxrwxrwx1rootroot18Jun212008/etc/localtime->/var/etc/localtime
[xx:~]>ls-l/var/etc/localtime
lrwxrwxrwx1rootroot30May1409:46/var/etc/localtime->/usr/share/zoneinfo/US/Eastern
开始时,我以为应该是和/etc/localtime指向的时区一样的,接着才发现原来java在没有TZ环境变量时取的是/etc/sysconfig/clock
中的时时区。Sun上面有和我这种情况相关的bug-DefaulttimezoneisincorrectlysetoccasionallyonLinux(http://bugs.sun.com/view_bug.do?bug_id=6456628),里面描述了javavm取的默认timezone的算法:
1)如有环境变量TZ设置,则用TZ中设置的时区
2)在/etc/sysconfig/clock文件中找"ZONE"的值
3)如何2)都没,就用/etc/localtime和/usr/share/zoneinfo下的时区文件进行匹配,如找到匹配的,就返回对应的路径和文件名。
下面是我的测试:
java测试程序(来自:http://www.minaret.biz/tips/timezone.html)
importjava.util.Date;
importjava.util.TimeZone;
publicclassTimeTest{
publicstaticvoidmain(Stringargs[]){
longtime=System.currentTimeMillis();
Stringmillis=Long.toString(time);
Datedate=newDate(time);
System.out.println("Currenttimeinmilliseconds="+millis+"=>"+date.toString());
System.out.println("Currenttimezone:"+TimeZone.getDefault().getID());
}
}
查看本地时区设置:
[xx:~]>echo$TZ
(TZ环境变量没设置)
[xx:~]>ls-l/var/etc/localtime
lrwxrwxrwx1rootroot30May1402:24/var/etc/localtime->/usr/share/zoneinfo/US/Arizona
[xx:~]>date
FriMay1402:30:05MST2010
date命令显示的时间和/var/etc/localtime指向的时间一致
查看/etc/sysconfig/clock中的时区设置(RedhatLinux)
[xx:~]>cat/etc/sysconfig/clock
ZONE="America/New_York"
UTC=false
ARC=false
[xx:~]>javaTimeTest
Currenttimeinmilliseconds=1273829564349=>FriMay1405:32:44EDT2010
Currenttimezone:America/New_York
Currenttimezonedisplay:EasternStandardTime
[xx:~]>
TimeTest运行结果显示,javavm取得的的默认时区和/etc/sysconfig/clock中的设置一样。让我们来验证一下:
1)修改/etc/sysconfig/clock:
[xx:~]>vim/etc/sysconfig/clock
ZONE="US/Central"
UTC=false
ARC=false
2)再运行TimeTest
[xx:~]>javaTimeTest
Currenttimeinmilliseconds=1273829718269=>FriMay1404:35:18CDT2010
Currenttimezone:US/Central
Currenttimezonedisplay:CentralStandardTime
修改/var/etc/localtime指向时区
先看看date显示:
[xx:~]>date
FriMay1402:36:37MST2010
[xx:~]>sudoln-sf/usr/share/zoneinfo/US/Central/var/etc/localtime
查看date命令结果的变化
[xx:~]>date
FriMay1404:37:41CDT2010
可以到时间和时区自动变了
好,再看另外一种情况:当TZ这个环境变量存在并有设置时
首先看看TZ的值为空时,date命令结果的变化
[xx:~]>exportTZ=
[xx:~]>date
FriMay1409:41:04UTC2010
时间变了,且时区显示是UTC(UniversialTimeCoordination).
也看看TimeTest的运行结果:
[xx:~]>javaTimeTest
Currenttimeinmilliseconds=1273830175690=>FriMay1409:42:55GMT2010
Currenttimezone:GMT
Currenttimezonedisplay:GreenwichMeanTime
[xx:~]>
可以看出,javavm默认时区是GMT。
给TZ赋某个时区:
[xx:~]>exportTZ="US/Central"
[xx:~]>date
FriMay1404:44:40CDT2010
date的输出跟着TZ变量马上调整过来
运行TimeTest
[xx:~]>javaTimeTest
Currenttimeinmilliseconds=1273830328966=>FriMay1404:45:28CDT2010
Currenttimezone:US/Central
Currenttimezonedisplay:CentralStandardTime
TimeTest取得和TZ一样的时区
[xx:~]>sudoln-sf/usr/share/zoneinfo/US/Eastern/var/etc/localtime
[xx:~]>date
FriMay1404:46:16CDT201
[xx:~]>exportTZ="US/Eastern"
[xx:~]>date
FriMay1405:47:58EDT2010
参考资料:
1.DefaulttimezoneisincorrectlysetoccasionallyonLinux
http://bugs.sun.com/view_bug.do?bug_id=6456628
2.如何设置Linux时间
http://www.hypexr.org/linux_date_time_help.php
3.解决javadefaultTimezone问题的方法
http://www.minaret.biz/tips/timezone.html