先说结论,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
ln -s 是不是写反了