Java TimeZone 和 Linux TimeZone问题

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

相关推荐

86981538 / 0评论 2014-07-24