我在美国的Ubuntu服务器中运行一个Java应用程序,并配置了CEST时区。
如果我在终端中运行Date命令,它将以CEST Zone时间返回日期-这是完美的。
但是在Java中,如果我运行以下代码
System.out.println (new Date ());
它给了我EDT时间。 我缺少什么配置。
参见stackoverflow.com/questions/3010035/
从控制台中获取的显示中解释日期对象时必须小心,因为它们是使用运行该程序的VM的默认TimeZone格式化的(默认情况下是从OS的时区继承的)。
当然,您可以根据Jesper的回答提供您自己的TimeZone。但是在这样做的同时,我强烈建议您使用IANA时区标识符(例如America / New_York)而不是EST。之所以如此,是因为具有"标准"的缩写未考虑日光节约。
因此,如果仅在控制台上打印日期对象,而没有得到预期的结果,则很有可能将服务器时区设置为错误的值,或者将OS设置为错误的时区。
要更改JVM时区,可以在启动时使用此参数
-Duser.timezone="America/New_York"
tl; dr
世界标准时间:
Instant.now() // Instantiate an object capturing the current moment in UTC.
.toString() // Generate a String representing textually that date-time value using standard ISO 8601 format.
2018-03-16T00:57:34.233762Z
分区:
ZonedDateTime.now( ZoneId.of("Africa/Tunis" ) ) // Instantiate an object representing the current moment with a wall-clock time seed by people in a particular region (time zone).
.toString() // Generate a String representing textually that date-time value using standard ISO 8601 format wisely extended to append the name of the time zone in square brackets.
2018-03-16T01:57:34.233762+01:00[Africa/Tunis]
细节
Shailendra的答案是正确的。
另外,在Question中看到的Date类是麻烦的旧日期时间类的一部分,这些类现在已被遗留,完全被java.time类所取代。
java.util.Date的替换为java.time.Instant。 Instant类表示UTC时间轴上的时刻,其分辨率为纳秒(最多十进制的九(9)位数字)。
Instant::toString?始终使用UTC
调用旧类的Date::toString方法时,其作者选择的不幸行为是动态应用JVM的当前默认时区。这不会造成混乱。幸运的是,现代类无需添加任何时区即可说出简单的事实:Instant始终位于UTC中。
Instant.now().toString()
2018-03-16T00:57:34.233762Z
该字符串格式是标准的ISO 8601格式。最后的Z是Zulu的缩写,表示UTC。
CEST Zone time
没有名为CEST的时区。这样的3-4个字母名称是伪区域。它们不是标准化的。它们不是唯一的(!)。而是使用continent/region格式的正确时区。
ZoneId z = ZoneId.of("Europe/Paris" ) ;
您可以通过将ZoneId应用于Instant以获得ZoneDateTime,从UTC调整到这样的时区。
Instant instant = Instant.now() ;
ZonedDateTime zdt = instant.atZone( z ) ;
zdt.toString(): 2018-03-16T01:57:34.233762+01:00[Europe/Paris]
或使用快捷方式ZonedDateTime.now。
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
您也可以将ZonedDateTime调整为另一个时区。注意,java.time使用不可变对象。因此,在调整过程中,我们会基于原始对象得到一个新的独特对象,但又不会干扰原始对象。
ZoneId zNewYork = ZoneId.of("America/New_York" ) ;
ZonedDateTime zdtNewYork = zdt.withZoneSameInstant( zNewYork ) ;
zdtNewYork.toString(): 2018-03-15T20:57:34.233762-04:00[America/New_York]
非常清楚,Instant,zdt和zdtNewYork是三个单独的对象,它们代表时间轴上的同一时刻,同一点。相同的时刻,不同的时钟时间。
I have a Java Application running in my Ubuntu Server in USA and configure CEST Time Zone
仅供参考,一般来说,服务器默认时区的最佳做法是UTC。
更重要的是,服务器操作系统和JVM的当前默认时区应与Java应用程序无关。
不要隐式依赖JVM的当前默认时区,而应始终明确指定所需/期望的时区。如上面的代码所示,将可选的ZoneId参数传递给各种java.time方法。
(顺便说一下,Locale的同上-始终指定所需/预期的语言环境,而不是隐式依赖于当前默认值。)
关于java.time
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧版旧式日期时间类,例如java.util.Date,Calendar和SimpleDateFormat。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC驱动程序。不需要字符串,不需要java.sql.*类。
在哪里获取java.time类?
Java SE 8,Java SE 9和更高版本
内置的
标准Java API的一部分,具有捆绑的实现。
Java 9添加了一些次要功能和修复。
Java SE 6和Java SE 7
java.time的许多功能在ThreeTen-Backport中都被反向移植到Java 6和7。
安卓系统
更高版本的Android捆绑了java.time类的实现。
对于早期的Android(<26),ThreeTenABP项目改编了ThreeTen-Backport(如上所述)。请参阅如何使用ThreeTenABP…。
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval,YearWeek,YearQuarter等。
您说服务器配置为位于CEST时区,但是根据Java,默认时区为EDT。 Java从操作系统获取默认时区,因此您的服务器可能未正确设置为CEST。
如果要在特定时区中打印日期,请使用DateFormat并在其上设置时区:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
df.setTimeZone(TimeZone.getTimeZone("CET"));
System.out.println(df.format(new Date()));
注意:根据我的Java(Java 7u45),CEST不是有效的时区。您是说"英语四级考试"吗? (CEST是CET的夏季变体,但是如果您使用CET,则Java将在适当的时候自动在夏季显示时间)。