3

在闰秒之前和闰秒期间,调用似乎new Date()将返回 23:59:59 两次(一次在闰秒之前,一次在闰秒期间),而不是 23:59:59 和 23:59:60。

有没有办法(没有在应用程序中实现 NTP 客户端,或者检查时钟是否倒退或重复)来确定给定的秒是否是闰秒,以便正确呈现 23:59 :60 给用户?

就此而言,主机操作系统是否有任何挂钩来确定它是闰秒前还是闰秒后?

4

2 回答 2

7

让我们看看源代码java.util.Date

public Date() {
    this(System.currentTimeMillis());
}

所以这个问题可以理解为:

System.currentTimeMillis()产生 60 甚至 61 的闰秒值(正如规范所声称的那样)?

答案是严格意义上的:它取决于底层操作系统。但事实是:所有众所周知的操作系统,如 Windows、Linux、Apple、Android 都对闰秒一无所知。相反,这些操作系统可以随时进行任何时钟操作(设置回退等,与 NTP 服务器同步......)。因此,您不会使用Date-API 观察到闰秒。顺便说一句,值 61 是不可能的,因为 UTC 标准要求 UTC 与 UT1 的偏差永远不会超过 0.9 秒,因此不会插入双闰秒。

“61”的起源只是对早期 POSIX 规范的严重误解(现在这个错误已得到纠正)。不幸的是,旧的 Java 规范直到现在还没有得到纠正,导致了误解。

关于 Java-8:

是的,所谓的“Java Time-Scale”被正式指定为 UTC-SLS——基于一个过期的提案,其意图是针对 NTP 服务器的内部实现。现实世界中不存在 UTC-SLS 的实现。甚至Java-8 也没有实现 UTC-SLS。两个事实证明了这个说法:

  • Java-8 不包含闰秒表(这将是任何 UTC-SLS 实现的基础)。Threeten-project 最初拥有这样一个,但它被删除了(现在也从 backport 中删除了)。

  • java.util.Dateto的转换Instant仅为 1:1(请参阅源代码 - 撇开不同的精度毫秒与纳米)。请注意,java.util.DateAPI 中并未提及Instant所谓的“Java 时间刻度”。

Java 时间刻度用于所有日期时间类。这包括 Instant、LocalDate、LocalTime、OffsetDateTime、ZonedDateTime 和 Duration。

此外:起源java.util.Date于 1995 年(Java 被发明时),但 UTC-SLS 是在几年后提出的。

那么 Java-8 中还剩下什么作为闰秒支持呢?规范中的空词引起了很多混乱,仅此而已。

你还能做什么?在JDK的范围内根本没有。您需要的是具有内置闰秒数据的外部第三方库。一个例子是我的库 Time4J - 请参阅这篇文章。另一种选择可能是类UTCInstant的 Threeten-Extra 库。但我还没有测试它的转换为java.util.Date(似乎是可疑的?)。

于 2015-07-01T13:21:06.977 回答
2

根据Date 类的 Java8 文档,在闰秒期间调用 Date 将/确实正确返回:60 或:61。

所以你不需要做任何事情。

但是它是如何做到的有点神秘,因为底层的Instant 类在一天的最后 1000 秒内传播闰秒 - 所以最后几秒中的每一秒实际上都是 1.001 秒长 - 你的应用程序不会知道它是否是在闰秒与否。

于 2015-07-01T05:22:05.977 回答