在闰秒之前和闰秒期间,调用似乎new Date()
将返回 23:59:59 两次(一次在闰秒之前,一次在闰秒期间),而不是 23:59:59 和 23:59:60。
有没有办法(没有在应用程序中实现 NTP 客户端,或者检查时钟是否倒退或重复)来确定给定的秒是否是闰秒,以便正确呈现 23:59 :60 给用户?
就此而言,主机操作系统是否有任何挂钩来确定它是闰秒前还是闰秒后?
在闰秒之前和闰秒期间,调用似乎new Date()
将返回 23:59:59 两次(一次在闰秒之前,一次在闰秒期间),而不是 23:59:59 和 23:59:60。
有没有办法(没有在应用程序中实现 NTP 客户端,或者检查时钟是否倒退或重复)来确定给定的秒是否是闰秒,以便正确呈现 23:59 :60 给用户?
就此而言,主机操作系统是否有任何挂钩来确定它是闰秒前还是闰秒后?
让我们看看源代码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.Date
to的转换Instant
仅为 1:1(请参阅源代码 - 撇开不同的精度毫秒与纳米)。请注意,java.util.Date
API 中并未提及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
(似乎是可疑的?)。
根据Date 类的 Java8 文档,在闰秒期间调用 Date 将/确实正确返回:60 或:61。
所以你不需要做任何事情。
但是它是如何做到的有点神秘,因为底层的Instant 类在一天的最后 1000 秒内传播闰秒 - 所以最后几秒中的每一秒实际上都是 1.001 秒长 - 你的应用程序不会知道它是否是在闰秒与否。