Java Date构造函数意外行为

时间:2018-03-15 05:54:33

标签: java date locale

我只是向Date的类构造函数提供2160000000(即1000 * 60 * 60 * 24 * 25 - 仅25天)的值。我希望看到这里将是1970-01-26 00:00:00,但我收到的是1970-01-26 03:00:00(另外三个小时)!我没有发现这个构造函数也依赖于JVM语言环境设置的任何要点,我找到的只是关于闰秒的信息。但闰秒不是同一个月的三个小时。但无论如何,我已经改变了一个测试方法的默认语言环境(美国的一个。我位于欧洲)只是为了实验,但没有任何改变。

我刚收到这个(我之前已经解释过,你知道的)     Date date = new Date(1000* 60 * 60 * 24 * 25); (这只是为了举例)。我只是使用调试器看到实际值,这就是全部:

enter image description here

3 个答案:

答案 0 :(得分:4)

您获得了预期的DateDate为1970-01-26 00:00:00 UTC 。此时间点相当于UTC偏移+03:00的1970-01-26 03:00:00。

在调试器中,您正在查看Date对象的私有字段。客户没有记录这些(这就是重点),所以不要指望任何特定的值。

我相信你会发现Instant.ofEpochMilli(1000L * 60 * 60 * 24 * 25)不那么混乱。或者更好,Instant.EPOCH.plus(Duration.ofDays(25))。 java.time,现代Java日期和时间API,可以更好地使用。如果您确实需要Date用于您不想立即更改的旧API,我建议先使用Instant,然后使用Date.from(yourInstant),以便尽量减少使用(并且依赖于过时且令人困惑的Date类。

最后,更改区域设置没有任何区别。虽然时区和UTC偏移密切相关(在某种程度上,有些人认为它是相同的:-) locale并没有真正与它们有任何关系。相反,该区域设置处理一组用户的语言和文化规范 - 它甚至不需要与地理位置相关联。

链接: All about java.util.Date

答案 1 :(得分:2)

您认为您所看到的小时差异与您所在国家/地区的时区相同(GMT + 3)是巧合吗?我想不是。

SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = dateFormat.parse("/*TimeToParse*/");

这肯定会有所帮助。

编辑:如果您在调试屏幕截图中检查zoneOffset和ZoneInfo值,您会更好地理解。

答案 2 :(得分:2)

TL;博士

Instant.ofEpochMilli( 2_160_000_000L )

java.time

The Answer by Acar可能是正确的:您对Date::toString的不幸设计感到困惑,以便在生成字符串时动态应用JVM的当前默认时区。 许多的原因之一是永远不会使用麻烦的Date类,现在由 java.time 类取代。

要使用分辨率为纳秒的UTC时间轴上的时刻表示,请使用Instant

Instant instant = Instant.ofEpochMilli( 2_160_000_000L ) ;

如果您的真实意图是将25天整天表示为未附加到时间线的时间段,请使用Period

LocalDate today = LocalDate.now( ZoneId.of( “Africa/Tunis” ) ) ;

Period p = Period.ofDays( 25 ) ;
LocalDate later = today.plus( p ) ;