正确处理闰秒

xir*_*irt 3 java time ntp unix-timestamp leap-second

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

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

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

Men*_*ild 7

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

public Date() {
    this(System.currentTimeMillis());
}
Run Code Online (Sandbox Code Playgroud)

所以问题可以解读为:

System.currentTimeMillis()产生闰秒值60甚至61(如规格假装)?

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

"61"的起源只是早期POSIX规范的严重误解(此错误现已得到纠正).不幸的是,旧的Java规范尚未得到纠正,直到现在才引起误解.

关于Java-8:

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

  • Java-8不包含闰秒表(这将是任何UTC-SLS实现的基础).Threeten项目最初持有这样一个,但它已被删除(现在也后端移除).

  • 从转换java.util.DateInstant仅仅是1:1(见源代码-撇开不同精度米利斯与毫微秒).注意,java.util.DateInstant所谓的"Java时间尺度" 的API中没有提到.

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

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

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

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