Linux Machine(UTC时区)中的Java程序以HDT时区而不是UTC时区返回日期

时间:2019-10-28 11:24:02

标签: java linux date timezone java-7

我在UTC时区有一台Linux机器。

[user@test packages]$ date +'%:z %Z'
+00:00 UTC

运行cat /etc/localtime似乎也表明我的计算机处于UTC时区;

[user@test ~]$ cat /etc/localtime
f2UTCTZif2UTC
UTC0

但是,在Java 1.7下运行tomcat的应用程序中调用logger.info(new Date())会返回类似Mon Oct 28 01:51:39 HDT 2019

这很奇怪,因此我创建了一个简单的Java程序进行测试:

import java.util.Date;

class Test
{
        public static void main (String args[])
        {
                Date dt = new Date();
                System.out.println(dt);
        }
}

编译并运行

[user@test]$ /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.211.x86_64/bin/javac Test.java
[user@test]$ /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.211.x86_64/bin/java Test
Mon Oct 28 02:08:49 HDT 2019

我的问题是为什么我的Linux实用程序以UTC格式返回日期,而我的Java应用却以HDT格式返回日期(我什至都​​不知道HDT是什么)。

由于我要维护的应用程序是旧版应用程序,因此我无法使用Joda Time或升级到Java8或更高版本,因为这将导致大量代码更改。

2 个答案:

答案 0 :(得分:2)

我终于可以通过以下操作对其进行修复:

  • 运行ln -fs /usr/share/zoneinfo/UTC /etc/timezone
  • 修改/etc/sysconfig/clock

在读完https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6456628

之后,我想到了/etc/sysconfig/clock

答案 1 :(得分:1)

tl; dr

请勿使用旧版类Date

  • Instant.now()
    用于UTC的当前时刻。
  • ZonedDateTime.now( ZoneId.of( "Pacific/Honolulu" ) )
    用于特定时区的当前时刻。

2020-02-18T05:28:11.146726Z

2020-02-17T19:28:11.146726-10:00 [太平洋/火奴鲁鲁]

详细信息

首先,您应该知道您的java.util.Date实际上是UTC时刻,但是它的toString方法在生成文本时会动态应用JVM当前的默认时区。很混乱。 从不使用此类的的众多原因之一。

DateCalendar和其他传统的日期时间类在几年前被JSR 310所采用的 java.time 所取代。

避免使用默认时区

使用 java.time 类,您可以轻松编写不依赖默认时区的代码。您可以明确指定所需的UTC偏移量或时区,无论是UTC本身(零小时-分钟-秒的偏移量)还是time zone like Pacific/Honolulu

UTC

如果要使用UTC跟踪时刻,请使用Instant

Instant instant = Instant.now() ;

Instant::toString方法以标准ISO 8601格式生成文本。该标准定义的格式是为数据交换而设计的。

String output = instant.toString() ;

输出:2020-02-18T05:28:11.146726Z

最后的Z表示UTC,并发音为“ Zulu”。

分区

如果您想在夏威夷人使用的挂钟时间看到同一时刻,请应用ZoneId以获得ZonedDateTime

请勿使用2-4个字母的缩写,例如HDTESTIST,因为它们不是真正的时区,不是标准化的,也不是甚至唯一的(!)。

Continent/Region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland

ZoneId z = ZoneId.of( "Pacific/Honolulu" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

ZonedDateTime::toString方法通过在时区的名称后面加上方括号来明智地扩展ISO 8601格式。

String output = zdt.toString() ;

请参阅此code run live at IdeOne.com

outputZdt:2020-02-17T19:28:11.146726-10:00 [太平洋/火奴鲁鲁]


Table of date-time types in Java, both modern and legacy


关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规范为JSR 310

Joda-Time项目(现在位于maintenance mode中)建议迁移到java.time类。

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?

相关问题