Java TimeZone 和 Linux TimeZone问题
转载连接: https://my.oschina.net/huawu/blog/4646
昨天发现跑在Linux上的java程序获取的默认时区有问题。
由于我所用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/Eastern
开始时,我以为应该是和/etc/localtime指向的时区一样的,接着才发现原来java在没有TZ环境变量时取的是 /etc/sysconfig/clock
中的时时区。 Sun上面有和我这种情况相关的bug - Default timezone is incorrectly set occasionally on Linux**(http://bugs.sun.com/view_bug.do?bug_id=6456628)**, 里面描述了java vm取的默认timezone的算法:
1)如有环境变量 TZ设置,则用TZ中设置的时区
2)在 /etc/sysconfig/clock文件中找 “ZONE”的值
3)如何2)都没,就用/etc/localtime 和 /usr/share/zoneinfo 下的时区文件进行匹配,如找到匹配的,就返回对应的路径和文件名。
下面是我的测试:
java测试程序(来自:http://www.minaret.biz/tips/timezone.html)
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());}
}
查看本地时区设置:
[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
- 如何设置Linux时间
http://www.hypexr.org/linux_date_time_help.php - 解决java default Timezone 问题的方法
http://www.minaret.biz/tips/timezone.html
————-补充:
1.jre时区支持查看目录:
java.home/jre/lib/zi
2.linux时区支持查看目录:
ls -l /usr/share/zoneinfo
单个java应用,可以在在启动时候设置时区:
java -Duser.timezone=GMT+08 ...jar
3.liunx系统时区设置详细连接:
http://coolnull.com/235.html
4.没有权限的情况下,如何实现改动
1)Java启动时候增加
-Duser.timezone=对应时区
2)linux修改:
export TZ='Asia/Jakarta' ----测试结果单引号有效果,双引号有问题echo $TZ
可以通过命令tzselect
选择对应时区,显示正确的格式
遇到问题:
$ echo $TZ$ ls -l /etc/localtimelrwxrwxrwx 1 root root 33 Oct 28 2016 /etc/localtime -> /usr/share/zoneinfo/Asia/Shanghai
$ cat /etc/sysconfig/clock ZONE="Asia/Jakarta"UTC=falseARC=false
结果启动时候使用的是/Asia/Shanghai时区,和上面的时区处理顺序有差异!(暂时没有权限修改测试,待解决)
/etc/sysconfig/clock
配置文件里面支持 UTC,ARC,SRM,ZONE 这几个配置选项。UTC – 指定 BIOS 中保存的时间是否是 GMT/UTC 时间,true 或 yes 表示 BIOS 里面保存的时间是 UTC
时间,false 或 no 表示 BIOS 里面保存的时间是本地时间。 ZONE – 指定时区,ZONE
的值是一个文件的相对路径名,这个文件是相对 /usr/share/zoneinfo 目录下的一个时区文件。比如 ZONE
的值可以是:“Asia/Shanghai”, “US/Pacific”, “UTC” 等(默认为ZONE=”Etc/UTC”)。 ARC –
这个选项一般配置 false 或 no,在一些特殊硬件下才配置该选项为 true 或 yes。 SRM – 同 ARC,该选项一般配置
false 或 no,在一下特殊硬件下才配置该选项为 true 或 yes
。
遇到比较奇葩的情况:
美国服务器:
查看系统时区为:
date -RTue, 11 Jul 2017 18:59:13 +0700
$echo $TZ$ cat /etc/timezone
Asia/Shanghai$cat /etc/sysconfig/clock
ZONE="Asia/Jakarta"
UTC=false
ARC=false
如果java启动的时候不设置时区,默认为时区为UTC+07的时区
如果java启动时候配置为:
java -server -Duser.timezone=UTC+07
则有效果,时区为+7时区
如果java启动时候配置为:
java -server -Duser.timezone=UTC+06
则无效果,时区还是为+7时区
如果java启动时候配置为:
java -server -Duser.timezone=UTC+08
则有效果,但是时区是为+0时区
如果java启动时候配置为:
java -server -Duser.timezone=GMT+06
则有效果,时区还是为+6时区
查询了JDK底层代码:
又对GMT 格式的专门解析方法:
static final String GMT_ID = "GMT"
private static TimeZone getTimeZone(String ID, boolean fallback) {TimeZone tz = ZoneInfo.getTimeZone(ID);if (tz == null) {tz = parseCustomTimeZone(ID);if (tz == null && fallback) {tz = new ZoneInfo(GMT_ID, 0);}}return tz;}private static final TimeZone parseCustomTimeZone(String id) {int length;// Error if the length of id isn't long enough or id doesn't// start with "GMT".if ((length = id.length()) < (GMT_ID_LENGTH + 2) ||id.indexOf(GMT_ID) != 0) {return null;}ZoneInfo zi;// First, we try to find it in the cache with the given// id. Even the id is not normalized, the returned ZoneInfo// should have its normalized id.zi = ZoneInfoFile.getZoneInfo(id);if (zi != null) {return zi;}int index = GMT_ID_LENGTH;boolean negative = false;char c = id.charAt(index++);if (c == '-') {negative = true;} else if (c != '+') {return null;}int hours = 0;int num = 0;int countDelim = 0;int len = 0;while (index < length) {c = id.charAt(index++);if (c == ':') {if (countDelim > 0) {return null;}if (len > 2) {return null;}hours = num;countDelim++;num = 0;len = 0;continue;}if (c < '0' || c > '9') {return null;}num = num * 10 + (c - '0');len++;}if (index != length) {return null;}if (countDelim == 0) {if (len <= 2) {hours = num;num = 0;} else {hours = num / 100;num %= 100;}} else {if (len != 2) {return null;}}if (hours > 23 || num > 59) {return null;}int gmtOffset = (hours * 60 + num) * 60 * 1000;if (gmtOffset == 0) {zi = ZoneInfoFile.getZoneInfo(GMT_ID);if (negative) {zi.setID("GMT-00:00");} else {zi.setID("GMT+00:00");}} else {zi = ZoneInfoFile.getCustomTimeZone(id, negative ? -gmtOffset : gmtOffset);}return zi;}
Java TimeZone 和 Linux TimeZone问题相关推荐
- Linux TimeZone设置
最近遇到一个有关timezone的问题:有些application需要环境变量TZ,可是我们刚刚装好的RHEL没有设置TZ,而我又没有root权限去改,查了半天资料,发现所有对timezone的改动都 ...
- 第90节:Java中的Linux基础
第90节:Java中的Linux基础 linux是装载虚拟机上面的: JDK依赖包: yum install glibc.i686MYSQL依赖包: yum -y install libaio.so. ...
- 在linux怎样运行java,怎么在linux运行java
怎么在linux运行java [2021-02-01 00:44:14] 简介: php去除nbsp的方法:首先创建一个PHP代码示例文件:然后通过"preg_replace(" ...
- linux收缩java位置,找到linux中当前java的安装位置
先看java -version $java version "1.8.0_111" Java(TM) SE Runtime Environment (build 1.8.0_111 ...
- linux钟java运行命令,在java中运行linux命令
我想在java中运行"ls"命令,我的代码是- 注意: - 我正在使用WINDOWS.在java中运行linux命令 import java.io.IOException; pub ...
- java查看日志命令_[Java教程]【Linux】linux查看日志文件内容命令tail、cat、tac、head、echo...
[Java教程][Linux]linux查看日志文件内容命令tail.cat.tac.head.echo 0 2017-11-14 12:00:29 linux查看日志文件内容命令tail.cat.t ...
- java jcsh执行linux命令,java jcsh执行linux命令
java jcsh执行linux命令 [2021-02-03 01:26:29] 简介: php去除nbsp的方法:首先创建一个PHP代码示例文件:然后通过"preg_replace(&q ...
- 你的java程序有没有内存泄露,java进程在linux系统中rss计算方式是什么样的?
java进程在linux系统中rss计算方式如下: RSS = Heap size + MetaSpace + OffHeap size 其中OffHeap由线程堆栈,直接缓冲区,映射文件(库和jar ...
- linux java -cp lt; .txt_补交 20155202 蓝墨云班课 编写MyCP.java 实现类似Linux下cp XXX1 XXX2的功能...
蓝墨云班课 编写MyCP.java 要求: 编写MyCP.java 实现类似Linux下cp XXX1 XXX2的功能,要求MyCP支持两个参数: java MyCP -tx XXX1.txt XXX ...
最新文章
- Jmeter Md5加密操作之-------BeanShell PreProcessor
- Hibernate一对多(注解)
- [Java] grails 安装手记
- 产品经理在工作中如何进行沟通
- matlab重置矩阵大小resize,JS resize事件:窗口重置
- 【渝粤教育】10259k2_经济学基础_21秋考试
- Pandas-层次化索引
- Effective C++ ——设计与声明
- Spring MVC请求处理流程分析
- js中的onscroll的用法
- networking常用命令
- ButterKnife 8.6.0 使用
- 新基建安全怎么做?看看这场院士领衔的高峰对话
- android设置背景渐变色,Android背景渐变色(shape,gradient)
- Android编译中m、mm、mmm的区别
- 用计算机开3次方,android系统计算器开3次方
- 京东云引擎:免费好用的web应用托管平台
- 医疗器械行业按下“加速键”,华瑭医疗的总代生意却并不好做
- Shopee聊聊客服工作日常
- 2013年5月中国数码相机市场分析报告
热门文章
- 在中国,办事吃饭是常事,但是这样的饭局往往是不好应付的,诸多的潜规则等待你去体味。为了不出丑,呵呵,还是提早学习下为好。
- c语言如何使一行抹去,c语言,clrscr();怎么清除指定的内容,不是页面都清除掉。比如第一行是标题,我只想清除第二行...
- 将bolg同时部署到Github和coding
- opencv-python阈值分割
- Java IO流大闯关--IO流的常用实现类
- MySQL——基础篇
- 三菱FX3U与4台三菱变频器专用指令通讯案例 功能:采用三菱FX3U PLC与4台三菱变频器E740进行通讯
- java统计用户网页停留时间,前端js计算用户在网页的停留时间和用户是否在点击浏览的时间...
- MSSQL 数据库被标记为SUSPECT状态,如何恢复?
- 企业公关形象传播及效果评估