我正在做一个 Java7 项目,我们需要一个国际原子时间的时间戳。我发现了一些与此相关的其他问题,这些问题指向 JSR-310 和 ThreeTen 项目(正在实施 JSR-310):
http://www.coderanch.com/t/549178/java/java/TAI-Atomic-Time-International
但是,我正在努力弄清楚 Java 7 使用什么以及从哪里获取它。ThreeTen 似乎有旧的 SourceForge 和 GitHub 页面,以及一个 OpenJDK 页面。
我找到了 Java 7 backport,但是从 Maven 下载它后,它不包含我真正需要的 TAIInstant 类(TIAInstant 类在 ThreeTen SourceForge JavaDoc 中的 javax.time.TAIInstant 下列出)。
为了完整起见,这是我的 pom.xml 的摘录:
<dependency>
<groupId>org.threeten</groupId>
<artifactId>threetenbp</artifactId>
<version>0.8.1</version>
</dependency>
我应该使用其他东西,我应该从哪里得到它?
注意:抱歉,我无法提供指向我所指的所有页面的链接,StackOverflow 不会让我在没有更高代表的情况下每个帖子有 > 2 个链接。
[编辑]
想要 TAI 的原因是我需要一个单调递增的时间戳,我相信 TAI 满足(即使在正负闰秒期间,因为它不关心闰秒,所有秒数都一样,包括闰秒)。
从各种来源阅读了有关 POSIX / Unix 时间的信息后,我仍然不清楚 Unix 时间在闰秒内到底发生了什么。我知道 Unix 时间在指代 UTC 时间方面是模棱两可的,但我不清楚在闰秒发生的那一刻 Unix 时间会发生什么?例如,Unix 时间会“暂停”还是倒退?也许更重要的是,即使它不应该根据 Unix 时间规范,Unix 实现是否真的遵守关于闰秒的规范......?
最后,我是否正确地说 System.currentTimeMillis() 将获得相当于 POSIX 时间(尽管以毫秒而不是秒为单位)?
注意,我需要一个可跨 JVM 和机器移植的对象(排除 System.nanoTime() 或类似的)。
[结论]
TAI
TAI 是一个测量时间的系统,其中每一秒都被计算并且“所有秒数都相等” - 即。每一秒包含相同的时间段,所有秒(包括闰秒)都计入总秒数。这意味着 TAI 中的秒数(从某个任意起点开始计算,例如 Unix 纪元)是一个单调递增的整数。
POSIX 时间
POSIX 时间是测量时间的标准(不是实现)。它将每一天定义为恰好有 86400 秒。因此,POSIX 时间不计算闰秒(因为偶尔一分钟可能有 61 秒,导致天数 >86400 秒,理论上一分钟可能有 59 秒,导致天数 <86400 秒)。这意味着 POSIX 中的“秒”具有可变长度,并且在闰秒之前/期间/之后不久,POSIX 时钟可能会跳过几秒或重复它们。具体来说,Meno Hochschild 在他的回答中引用的 POSIX 规范指出:“自 Epoch 以来的实际时间与当前秒数之间的关系是未指定的。”
UTC
UTC 是与地球围绕太阳运动的方式有关的时间标准,旨在保持太阳位置与一天中的时间(在阈值内)之间的关系。即在地球的 UTC+0 区域,太阳总是在 UTC 时间的中午处于最高位置。闰秒(正或负)是必要的,因为地球自转的速度不是固定的,并且它不会以可预测的方式变化(这意味着我们无法预测何时需要闰秒 - 或者它们是正闰秒还是负闰秒)
代表时间
在我看来,TAI 和 POSIX 都是“秒数”的表示(即计算机实际存储的容易的东西),而 UTC 是时间的“人类解释”(即年/月/日Hour:Minute:Second.millisecond) 通常不由计算机内部存储。
翻译时间
鉴于上述情况,从 POSIX(不计算闰秒)到 TAI(计算闰秒)存在许多问题:
- 它需要维护一个表/闰秒计数来将任何 POSIX 时间转换为 TAI 时间
- 即使解决了第 1 点,上述 POSIX 规范也不能保证闰秒期间会发生什么,因此在这种情况下,我们无法准确表示一个明确的时间
- 如果多个系统必须通信,在它们之间传递时间戳,我们必须保证闰秒表/计数保持一致
另一方面,很容易从 POSIX 转换为 UTC 的“人类解释”。它不需要闰秒的知识,因为它只是假设每天都有相同的秒数(尽管其中一些“秒”实际上具有不同的时间长度)。在实践中,您只需使用 POSIX 规范中公式的倒数来获得各种 UTC 时间分量(再次,请参阅 Meno Hochschild 引用的 POSIX 规范)。