【问题标题】:Do Java system milliseconds take account of leap seconds?Java系统毫秒是否考虑闰秒?
【发布时间】:2013-04-07 23:46:12
【问题描述】:

java 函数 System.currentTimeMillis() 显然返回自 1970 年 1 月 1 日以来的秒数。但是,根据wikipedia.org/wiki/Leap_second,自 1972 年以来已经有 25 个闰秒。这意味着自 1970 年 1 月 1 日以来的实际秒数比天真的计算所暗示的要多 25 秒。 System.currentTimeMillis() 会进行简单的计算并忽略闰秒吗?

【问题讨论】:

  • 这很容易测试。
  • @RobertHarvey:没错,但这只会告诉你关于 that OS 上的 that JVM 版本的一些信息。最好问问标准是否能保证什么。

标签: java datetime time


【解决方案1】:

正式而言,这取决于操作系统和实施 - 至少对于 Date 而言。来自java.util.Date的文档:

尽管 Date 类旨在反映协调世界时 (UTC),但它可能并不完全如此,这取决于 Java 虚拟机的主机环境。几乎所有现代操作系统都假定在所有情况下 1 天 = 24 × 60 × 60 = 86400 秒。然而,在 UTC 中,大约每隔一两年就会多出一秒,称为“闰秒”。闰秒总是作为一天的最后一秒添加,并且总是在 12 月 31 日或 6 月 30 日。例如,由于添加了闰秒,1995 年的最后一分钟是 61 秒。大多数计算机时钟不够准确,无法反映闰秒的区别。

我怀疑您会发现,尽管您的计算机时钟与 UTC 大致对齐,但这是通过 NTP 或类似方法定期校正时钟完成的,而不是操作系统真正实现闰秒。 p>

我相信 JRE 库通常确实假设 86400 秒。它让生活如此变得更加简单,而且如果你要纠正不准确的系统时钟,你也可以这样纠正闰秒。

您确实想计算出您感兴趣的内容。如果您需要一种使用闰秒来表示日期和时间的方法,那么标准 Java 库可能不适合您。据我所知,即使JSR-310 也不再支持闰秒(这对大多数开发人员来说是一个非常明智的决定)。

【讨论】:

  • 我在 Android 4.2 和 Windows 7 上做了一些测试,假设每天正好有 86400 秒,System.currentTimeMillis() 确实是自 1970 年 1 月 1 日以来的毫秒数。因此,确实忽略了闰秒,但正如您所说,计算机显示正确的时间(包括闰秒),因为它们的时钟会定期更正:-)。
  • @Stochasticly:测试太弱了。它不会显示系统如何支持闰秒(POSIX、Mills、smear、ntp、TAI(如果在后一种情况下输入是 1970TAI))。
  • 作为尝试实施“delay_length_in_nanoseconds = (end_time - now) * scale”的人,你不能低估我多么讨厌那些认为可以忽略闰秒的人。
【解决方案2】:

查看 currentTimeMillis() 的 Javadoc,它引用了 documentation of the Date class,它有这样的说法:

尽管 Date 类旨在反映协调世界时 (UTC),但它可能并不完全如此,这取决于 Java 虚拟机的主机环境。几乎所有现代操作系统都假定在所有情况下 1 天 = 24 × 60 × 60 = 86400 秒。然而,在 UTC 中,大约每隔一两年就会多出一秒,称为“闰秒”。闰秒总是作为一天的最后一秒添加,并且总是在 12 月 31 日或 6 月 30 日。例如,由于添加了闰秒,1995 年的最后一分钟是 61 秒。大多数计算机时钟不够准确,无法反映闰秒的区别。

所以回答你的问题:是的,闰秒被考虑在内。

【讨论】:

  • 但我认为这意味着结论应该是“不考虑闰秒”,即忽略,因为操作系统假设每天有 86400 秒。
  • 我理解它的方式:UTC 占闰秒。在现代操作系统中链接时区只是考虑了 UTC 和本地时间之间的时差(可能还有 DST,具体取决于使用情况)。另一种选择是,自 Unix 时间开始以来,每个人都已偏离 UTC 35 秒(来源:维基百科)。
  • 我认为你是对的,UTC 确实考虑了闰秒。但是,我的结论是,这些闰秒不包含在 System.currentTimeMillis() 中,正如我在对我标记为“答案”的答案的评论中所描述的那样。
【解决方案3】:

POSIX 要求系统时钟不承认闰秒的存在。 MS Windows 不能保证系统时钟硬件的质量(也不能保证存在),并且避开了 1 秒精度的保证。 Java 不能轻易地做任何底层系统拒绝做的事情。操作系统因international regulations 的历史而受阻,导致一种 IEEE 标准 (PTP) 需要闰秒,而另一种 (POSIX) 标准则拒绝闰秒。

【讨论】:

    【解决方案4】:

    检查是否考虑闰秒的一种简单方法是计算从纪元到当年任何一天的 00:00 所经过的秒数。

    如果该秒数与 00 模 60 一致,则不考虑闰秒,因为在 2013 年,您的模数应为 25(考虑过去 25 个闰秒)。

    【讨论】:

      【解决方案5】:

      我对@9​​87654321@做了一个小实验:

      java> new Date(1000L * 86400 * (365 * 4 + 1) * 12)
      java.util.Date res0 = Mon Jan 01 00:00:00 UTC 2018
      

      如您所见,使用了一个简单的“简单”算术,它只考虑闰年,而不是闰秒。不会增加或减少额外的秒数。

      更新:

      对于新的Instant 类也是如此:

      java> Instant.ofEpochMilli(1000L * 86400 * (365 * 4 + 1) * 12)
      java.time.Instant res0 = 2018-01-01T00:00:00Z
      

      【讨论】:

      • 仅供参考,Date 类现在是遗留的,被 Java 8 及更高版本中内置的 java.time 类所取代。具体来说,Instant 类替换了Date
      • @BasilBourque,谢谢!它是否与所讨论的闰秒问题有关?
      猜你喜欢
      • 2010-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-11
      • 2017-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多