Linux下jvm读取时区顺序问题

先说结论,jvm在读取linux的系统时区时

如果存在环境变量TZ,则jvm最优先读取环境变量TZ中的内容;

如果不存在环境变量TZ,会读取/etc/sysconfig/clock文件中的ZONE内容(需要引号);
若都不存在,则读取使用/etc/localtime文件内容所对应的时区
如果设置了-Duser.timezone,则使用指定的时区
在java中一般使用SimpleDateFormat来格式化及解析时间,如

Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String f = sdf.format(d);
System.out.println(f);

但是上边的代码存在一个问题,就是时区的问题,
SimpleDateFormat默认会使用系统时区来格式化当前Date对象表示的时间戳
这样在中国,如果服务器的时区为非东8区(GMT+8)时,会发生格式化出来的字符串并不是我们想要的。
所以在使用SimpleDateFormat时会设置时区

TimeZone tz = TimeZone.getTimeZone("GMT+8");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(tz);

但还有一个问题:

在redhat/centos中,有时使用date 和date -R时显示的系统时区没有问题(东8区、CTS、+0800)但是在代码中不设置时区时使用SimpleDateFormat时,得到的仍然不是我们想要的答案这是因为jvm在读取linux的系统时区时会读取/etc/sysconfig/clock文件中的ZONE内容,当仅仅更改/etc/localtime文件时,date命令返回的时间正确,但jvm读取的时区却正确。
如果存在环境变量TZ,则jvm最优先读取环境变量TZ中的内容

所以,在使用java进行日期处理时,为了避免上述麻烦,请在代码中显示的设定时区:

sdf.setTimeZone(tz);

附设置为东八区的配置

1、java -Duser.timezone=Asia/Shanghai

2、/etc/sysconfig/clock文件内容ZONE="Asia/Shanghai"

3、ln -s /etc/localtime /usr/share/zoneinfo/Asia/Shanghai

4、export TZ=Asia/Shanghai

参考:
http://my.oschina.net/huawu/blog/4646
http://linux.vbird.org/linux_server/0440ntp.php
http://bugs.java.com/view_bug.do?bug_id=6456628

“Linux下jvm读取时区顺序问题”的一个回复

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注