【异常】JVM 获取 Linux 时间错误(相差12小时)

阅读更多

问题

有两台Linux机器:

date 命令查看时间相同

通过 date 命令查看时间,发现两台机器区域语言和时间都相同:

 

JVM获取系统时间相差12小时

通过最基本的java代码 new Date() 获得时间,发现两台机器的系统时间相差12小时。
其中一台输出的时区与上述date命令相同,都是东八区(CST,中国标准时间)。
另一台输出的时区与date命令不符,是西五区(EDT,美国东部白昼时间)。
根据理论经度,东八区 与 西五区 相差13小时。但因为时值美国夏令时,时刻的值被“人为”调整,所以两台机器相差12小时。



 

 

解决方法

可以确定那台 date命令所得时区与JVM所得时区不同的 机器时间是错的。
修复方法就是以正确的方式重新设置系统时区:

ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

 

扩展

尽量自动化,减少对人肉运维的依赖

上述 date命令所得时区 与 JVM所得时区 不一致的问题,就是因为操作系统的时区未被正确设置。
这往往是不合格的“运维人员”“虎操作”导致的。
 

这种错误对于需要处理时间的Java应用而言是致命的!!!
不但无法得到正确的系统当前时间,也无法解析历史时间数据。 如,你之前在MySQL中正确存储了一个时间值,在这种错误的系统环境中,JVM解析这个来自数据库的行为也会出错。
 

此外,如果你的系统需要多台机上的Java应用基于各自的系统时间来合作完成某项业务,那么错误的那台机器会将你的业务逻辑完全破坏。
这种错误还非常难排查,你几乎不会去怀疑系统时区问题,因为date命令显示时区是正确的。

 

尽量使用维护成本低、准确无歧义的方式表示时间

不要使用时区缩写

时区缩写很可能有歧义。如,CST 可以表示:

  • 美国中部时间:Central Standard Time (USA)
  • 澳大利亚中部时间:Central Standard Time (Australia)
  • 中国标准时间:China Standard Time
  • 古巴标准时间:Cuba Standard Time

可以考虑用数值来表示时区。如,+08:00 表示东八区。

 

不要用夏令时

很多国家有 夏令时 和 冬令时 之分。在夏令时,时刻会被人为调整。
这种做法其实非常得不偿失,应尽量避免去涉及此类问题。

 

不要用年号纪年法

这也是一种“人祸”,非常浪费社会资源。
日本换个天皇就改个年号,平白浪费了很多社会资源。
这种纪年法展示的信息也与世界标准的公元纪年法格格不入,非常不利于信息交流。
 

很多非国际公认度量单位也对世界级的信息交流非常不友好,尽量不要使用。如,英尺、加仑、盎司。

 

《CentOS7修改时区的正确姿势》

《Java TimeZone 和 Linux TimeZone问题》

 

  • 【异常】JVM 获取 Linux 时间错误(相差12小时)_第1张图片
  • 大小: 1.9 KB
  • 【异常】JVM 获取 Linux 时间错误(相差12小时)_第2张图片
  • 大小: 2.4 KB
  • 【异常】JVM 获取 Linux 时间错误(相差12小时)_第3张图片
  • 大小: 2.6 KB
  • 查看图片附件

你可能感兴趣的:(【异常】JVM 获取 Linux 时间错误(相差12小时))