差异时区浏览器和Java

时间:2016-04-27 20:51:37

标签: javascript java datetime

我对同一时区内同一台机器上运行的浏览器(JS)和Java中的日期/时间/时区差异有疑问。我知道系统应该就时区达成一致(主要是UTC,使用Date.UTC)来避免这些问题。不过我认为这个例子应该可以正常工作。

为此,我使用浏览器(Chrome)创建了一些日期,并使用相同的millis来创建Date with Java。

这是一个我不明白的例子。请帮我理解。

Chrome(JavaScript):

new Date(1980,9,10,0,0,0,0) Fri Oct 10 1980 00:00:00 GMT+0200 (Mitteleuropäische Sommerzeit) The millis are: 339976800000

爪哇:

new Date(339976800000l) Thu Oct 09 23:00:00 CET 1980

请注意Java适用CET,而JavaScript适用CEST。

1 个答案:

答案 0 :(得分:1)

TL;博士

1980年至2016年期间Daylight Saving Time (DST)的定义发生了变化。

此前DST在九月的最后一个星期日结束,之后在十月的最后一个星期日结束。

详细答案

难题的缺失是知道计算中使用的特定时区。 您的问题和示例代码未能准确告诉我们使用了哪些时区。我的讨论假设您使用的时区类似于Europe/Berlin的时区(基于您对文本的使用显然是本地化的)在德语中),其DST的定义发生了变化。

CETCEST实际上不是时区。这些缩写不是标准化的,甚至也不是唯一的。 避免使用它们。

而是使用proper time zone names中定义的tz databasetrue time zoneoffset-from-UTC加上一组处理过去,现在和将来异常的规则,例如夏令时(DST)。

时区规则发生变化,经常发生变化。我想,无聊的政治家。

例如,Europe/Berlin在1980年改为在9月的最后一个星期日结束夏令时。因此,夏令时不适用于您1980年10月的日期。自1996年起适用欧盟规则,将夏令时延长至10月的最后一个星期日而不是9月。因此,DST 适用于您2016年10月10日的日期。

问题中的代码使用月份“9”,实际上是10月份的“10”。旧java.util.Date类的许多问题之一是它通过从零开始的计数来计算月数,0 = 1月。避免旧的日期时间类的许多原因之一。相比之下,在java.time中,10月的月份数确实是10,正如您所期望的那样,您可以使用Month枚举中的常量更加清晰。

顺便说一句,java.util.Date中另一个糟糕的设计选择是当问题中constructing a Date object as you did时,你的JVM的当前默认时区被应用,结果调整回UTC。这会使您的问题更加复杂,因为您在运行代码时没有报告使用的时区。

顺便说一下,JavaScript几乎与每个开发平台一样,对日期工作的支持很差。尽可能尝试使用Java及其内置的java.time框架。见Oracle Tutorial。您可以在以下示例代码中见证java.time的运行情况。我们将于1980年10月10日和2016年Europe/Berlin获得。

ZoneId zoneId = ZoneId.of ( "Europe/Berlin" );;

ZonedDateTime zdt_1980 = ZonedDateTime.of ( 1980 , Month.OCTOBER.getValue () , 10 , 0 , 0 , 0 , 0 , zoneId );
long seconds_1980 = zdt_1980.toEpochSecond ();

ZonedDateTime zdt_2016 = ZonedDateTime.of ( 2016 , Month.OCTOBER.getValue () , 10 , 0 , 0 , 0 , 0 , zoneId );
long seconds_2016 = zdt_2016.toEpochSecond ();

转储到控制台。

System.out.println ( "zoneId: " + zoneId );
System.out.println ( "zdt_1980: " + zdt_1980 + " | seconds_1980: " + seconds_1980 );
System.out.println ( "zdt_2016: " + zdt_2016 + " | seconds_2016: " + seconds_2016 );

您可以在结果中看到,从UTC(+01:00)提前一小时到现在比UTC(+02:00提前两小时),UTC的偏移量从一小时变为现在。不同之处在于重新定义了DST

所以,这解释了为什么你在1980年获得了“CET”而在2016年获得了“CEST”。你在2016年获得的S中的CEST意味着“夏天”,而“夏令时”意味着DST。在2016年的今年,10月的大部分时间都在“夏令时”(DST)。 1980年10月在DST /“夏令时”/“CEST”中

  

zoneId:欧洲/柏林

     

zdt_1980:1980-10-10T00:00 + 01:00 [欧洲/柏林] | seconds_1980:339980400

     

zdt_2016:2016-10-10T00:00 + 02:00 [欧洲/柏林] | seconds_2016:1476050400