我对同一时区内同一台机器上运行的浏览器(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。
答案 0 :(得分:1)
1980年至2016年期间Daylight Saving Time (DST)的定义发生了变化。
此前DST在九月的最后一个星期日结束,之后在十月的最后一个星期日结束。
难题的缺失是知道计算中使用的特定时区。 您的问题和示例代码未能准确告诉我们使用了哪些时区。我的讨论假设您使用的时区类似于Europe/Berlin
的时区(基于您对文本的使用显然是本地化的)在德语中),其DST的定义发生了变化。
CET
和CEST
实际上不是时区。这些缩写不是标准化的,甚至也不是唯一的。 避免使用它们。
而是使用proper time zone names中定义的tz database。 true time zone是offset-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