(Oracle)Java JVM如何知道闰秒正在发生?

(Oracle)Java JVM如何知道闰秒正在发生?,java,datetime,time,utc,Java,Datetime,Time,Utc,A 2015年6月30日。不同的操作系统处理这种情况的方式似乎不同。在我的特定案例中,我们运行的是一个Red Hat 6.4系统,它带有定制Java(JDK 1.7)软件,该软件严重依赖于时间。根据我发现的一些情况,我们系统的NTP守护进程将通过重复23:59:59两次来确保操作系统自动处理闰秒 我的问题是:如果我有一个长时间运行的JDK1.7进程,它如何知道闰秒正在发生?我的意思是,Java如何最终知道人们决定插入闰秒?文档似乎表明他知道闰秒,但似乎含糊不清。我可以假设JDK,当构造适当的Da

A 2015年6月30日。不同的操作系统处理这种情况的方式似乎不同。在我的特定案例中,我们运行的是一个Red Hat 6.4系统,它带有定制Java(JDK 1.7)软件,该软件严重依赖于时间。根据我发现的一些情况,我们系统的NTP守护进程将通过重复23:59:59两次来确保操作系统自动处理闰秒


我的问题是:如果我有一个长时间运行的JDK1.7进程,它如何知道闰秒正在发生?我的意思是,Java如何最终知道人们决定插入闰秒?文档似乎表明他知道闰秒,但似乎含糊不清。我可以假设JDK,当构造适当的
Date
对象或调用
Calendar.getInstance()
时,它是通过底层操作系统的日期时间处理来获得适当的“实时”时间值吗?(在我的例子中,这听起来像是重复第二个23:59:59,因为操作系统就是这样处理的)。

这取决于您的jdk版本。例如,如果您正在运行update 80,则可以检查:

JDK 7u80包含IANA时区数据版本2015a。有关更多信息,请参阅JRE软件中的时区数据版本

然后按照链接找到2015a。然后是:

新闰秒2015-06-30 23:59:60 UTC根据IERS公告C 49。(感谢蒂姆·帕雷尼。)

它以前似乎没有包含在内,因此如果您运行的是较旧版本的JDK 7,您可能不会得到调整。有关其内部工作方式的更多信息,请参阅

老实说,我从未测试过它在实践中是如何工作的。

by是正确的。这个答案添加了一些由对该答案的评论引发的想法。该评论提到了在计划闰秒时计算午夜经过的时间

这个答案也解决了最初的问题,指出对于实际使用,闰秒的问题是没有意义的,被日期-时间框架忽略了

忽略闰秒 据我所知,所有常见的Java日期时间框架都忽略闰秒。这些措施包括:

  • java.time
  • java.util.Date/.Calendar(现在已被java.time和Joda-time过时)
医生 下面是每个框架文档的摘录,显示它们实际上忽略了闰秒。粗体字的重点是我的

类的java.time文档:

…鉴于上述精确计时的复杂性,此Java API定义了自己的时间刻度,即Java时间刻度

Java时间刻度将每个日历日精确地划分为86400个细分,称为秒。这些秒数可能与SI秒数不同。它与事实上的国际民事诉讼时间尺度密切相关,而国际民事诉讼时间尺度的定义会不时变化

Java时间尺度对时间线的不同部分有着略微不同的定义,每个部分都基于作为民用时间基础的一致国际时间尺度。无论何时修改或替换国际商定的时间尺度,都必须为其定义一个新的Java时间尺度段。每个分段必须满足以下要求:

  • 爪哇时间尺度应与基本国际民用时间尺度密切匹配
  • 爪哇时间刻度应与每天中午的国际民用时间刻度完全一致
  • 爪哇时间尺度应与国际民用时间尺度具有精确定义的关系
截至2013年,Java时间尺度中目前有两个部分

对于1972-11-03(下文讨论的确切边界)至另行通知的时间段,一致同意的国际时标为UTC(带闰秒)。在此段中,Java时间刻度与UTC-SLS相同。在没有闰秒的日子,这与UTC相同。在有闰秒的日子里,闰秒平均分布在一天的最后1000秒,保持每天86400秒的样子

对于1972-11-03年之前任意向后延伸的段,一致国际时间标度定义为UT1,先入为主,相当于本初子午线(格林威治)上的(平均)太阳时间。在这一部分中,Java时间尺度与共识国际时间尺度相同。两段之间的精确边界是UT1=UTC在1972-11-03T00:00和1972-11-04T12:00之间的瞬间

使用JSR-310 API的Java时间尺度的实现不需要提供任何亚秒级的精确时钟,也不需要单调或平滑地进行。因此,实际执行UTC-SLS转换或以其他方式了解闰秒不需要实施。然而,JSR-310确实要求实现必须记录它们在定义表示当前时刻的时钟时使用的方法。有关可用时钟的详细信息,请参见时钟

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

:

Joda Time不支持闰秒。通过编写一个新的、专门的年表,或者对现有的ZonedTimeology类进行一些增强,可以支持闰秒。在这两种情况下,Joda Time的未来版本默认情况下都不会启用闰秒。大多数应用程序都不需要它,而且它可能会带来额外的性能成本

委员会:

第二个由0到61之间的整数表示;值60和61仅在闰秒出现,甚至仅在实际正确跟踪闰秒的Java实现中出现

据我所知,OpenJDK
// Joda-Time 2.8.1
DateTime startJoda = new DateTime( 2015, 06, 30, 23, 59, 00, DateTimeZone.UTC );
DateTime stopJoda = new DateTime( 2015, 07, 01, 00, 01, 00, DateTimeZone.UTC );
long elapsedMillisJoda = ( stopJoda.getMillis( ) - startJoda.getMillis( ) );

System.out.println( "startJoda: " + startJoda + " stopJoda: " + stopJoda + " = elapsedMillisJoda: " + elapsedMillisJoda );
// java.time
ZonedDateTime startZdt = ZonedDateTime.of( 2015, 06, 30, 23, 59, 00, 00, ZoneOffset.UTC );
ZonedDateTime stopZdt = ZonedDateTime.of( 2015, 07, 01, 00, 01, 00, 00, ZoneOffset.UTC );
long elapsedMillisZdt = startZdt.until( stopZdt, ChronoUnit.MILLIS );

System.out.println( "startZdt: " + startZdt + " stopZdt: " + stopZdt + " = elapsedMillisZdt: " + elapsedMillisZdt );
2015-06-30 23:59:59.316 18349217 [main] INFO  - Leaper's time is 488980799.316000 (Tue Jun 30 23:59:59 GMT-00:00 2015)
2015-06-30 23:59:59.817 18349718 [main] INFO  - Leaper's time is 488980799.816000 (Tue Jun 30 23:59:59 GMT-00:00 2015)
2015-07-01 00:00:00.317 18350218 [main] INFO  - Leaper's time is 488980800.317000 (Wed Jul 01 00:00:00 GMT-00:00 2015)
2015-07-01 00:00:00.817 18350718 [main] INFO  - Leaper's time is 488980800.817000 (Wed Jul 01 00:00:00 GMT-00:00 2015)
2015-07-01 00:00:01.318 18351219 [main] INFO  - Leaper's time is 488980801.318000 (Wed Jul 01 00:00:01 GMT-00:00 2015)