正确处理闰秒

时间:2015-07-01 04:34:43

标签: java time unix-timestamp ntp leap-second

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

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

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

2 个答案:

答案 0 :(得分:6)

让我们看一下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项目最初持有这样一个,但它已被移除(现在也removed from the backport)。

  • java.util.DateInstant的转换只是1:1(参见源代码 - 不同的精度毫秒与纳米分开)。请注意,在java.util.Date的API中未提及Instant所谓的" Java时间刻度"。

  

Java时标用于所有日期时间类。这包括   Instant,LocalDate,LocalTime,OffsetDateTime,ZonedDateTime和   持续时间。

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

那么Java-8还剩下什么作为闰秒支持?规范中的空字引起了很多混乱,没有别的。

你还能做什么?在JDK的范围内什么也不做。您需要的是具有内置闰秒数据的外部第三方库。一个例子是我的图书馆Time4J - 见article。另一个选项可能是库Threeten-Extra及其类UTCInstant。但是我没有测试它转换为java.util.Date(似乎是怀疑?)。

答案 1 :(得分:2)

根据Java8 documentation for the Date class,在闰秒期间调用日期将/正确返回:60或:61。

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

它是如何做到这一点有点神秘,因为潜在的Instant class在一天的最后1000秒内传播闰秒 - 因此每个最后几秒实际上将是1.001秒 - 并且你的申请不知道它是否处于闰秒之内。