我正在研究Java7项目,我们需要国际原子时的时间戳。我发现了一些与此相关的问题,指向JSR-310和ThreeTen Project(正在实施JSR-310):
How to get GPS Time and TAI time in Java?
http://www.coderanch.com/t/549178/java/java/TAI-Atomic-Time-International
然而,我正在努力研究究竟用于Java 7的内容以及从何处获取它。似乎有旧的SourceForge& ThreeTen的GitHub页面,以及OpenJDK页面。
我找到了Java 7的后端,但是从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不会让我拥有&gt;每个帖子有2个链接,没有更高的代表。
[编辑]
想要TAI的原因是我需要一个单调增加的时间戳,我相信TAI会满足(即使在正和负闰秒期间,因为它不关心闰秒平均计算所有秒数,包括闰秒。
从各种来源阅读了关于POSIX / Unix的时间后,我仍然不清楚在闰秒的Unix时间内发生了什么。我知道Unix时间在引用UTC时间方面是模棱两可的,但我不清楚在闰秒发生的瞬间Unix时间会发生什么? Unix时间是否暂停&#39;或者倒退例如?也许更重要的是,即使它不应该根据Unix时间规范,Unix实现是否真的遵守关于闰秒的规范......?
最后,我是否正确地说System.currentTimeMillis()将获得相当于POSIX时间(虽然以毫秒而不是秒)?
注意,我需要一个可以在JVM和机器上移植的对象(排除System.nanoTime()或类似的东西)。
[结论]
TAI
TAI是一个测量时间的系统,每秒计算一次,并且所有秒都相等&#39; - 即。每秒包含相同的时间段,所有秒数(包括闰秒)都计入总数中。这意味着TAI中的秒数(从某个任意起始点开始计算,例如Unix Epoch)是一个单调递增的整数。
POSIX时间
POSIX Time是用于测量时间的标准(不是实现)。它将每天定义为恰好有86400秒。因此,POSIX时间不计算闰秒(因为偶尔一分钟可能有61秒,导致天数> 86400秒,理论上一分钟可能有59秒,导致天数<86400秒)。这意味着&#39;秒&#39;秒在POSIX中具有可变长度,并且在闰秒之前/期间/之后不久,POSIX时钟可以跳过秒或重复它们。具体来说,Meno Hochschild在其答案中引用的POSIX规范指出,&#34;实际时间与自Epoch以来秒的当前值之间的关系未被指定。&#34;
UTC
UTC是一个时间标准,它与地球绕太阳运行的方式有关,旨在维持太阳位置与一天中的时间之间的关系(在一个阈值内)。即在地球的UTC + 0区域,太阳总是在UTC时间中午处于最高点。闰秒(正面或负面)是必要的,因为地球自转的速度并不固定,并且它不会以可预测的方式变化(这意味着我们无法预测何时需要闰秒 - 或者它们是否会是正闰秒或负闰秒)
代表时间
在我看来,TAI和POSIX都代表了秒数和秒数。 (即计算机实际存储容易的东西),而UTC是人类的解释。时间(即年/月/日时:分:秒。毫秒),通常不是由计算机内部存储。
翻译时间
鉴于上述情况,有许多问题从POSIX(没有任何闰秒计算)转换为TAI(计算闰秒):
另一方面,很容易从POSIX转换为UTC&#39;人工解释&#39;。它并不需要闰秒的知识,因为它只是假设每天都有相同的秒数(虽然其中一些&#39;秒&#39;实际上有不同的时间长度)。在实践中,您只需使用POSIX规范中的公式的倒数来获得各种UTC时间分量(再次参见Meno Hochschild引用的POSIX规范)。
答案 0 :(得分:4)
在JSR-310流程中删除了类TAIInstant
以及其他类似UTCInstant
的内容。该小组得出的结论是,这些是专业项目,并不一定是核心JDK。我仍然相信这是正确的决定。
这样做的结果是JSR-310对时间尺度的支持很少。然而,有一种正式定义的方法将JSR-310连接到时标,允许在给定精确源的情况下创建精确时钟。虽然不是每个人都喜欢这种解决方案,但它对主流来说是实用的。
总之,UTC和TAI的单独类的原始设计是合理的(并且是处理过去和未来事件所必需的)。但是,它对于JDK来说太专业了。
threeten-extra项目现在可以作为JDK 8的jar使用these classes。
答案 1 :(得分:3)
JSR-310-backport仅支持将包含在Java 8中的功能.TAI(和真正的UTC)将不是支持的功能,因此它不能在backport中。唯一的选择是尝试包含TAIInstant类的threeten-extra-project,但整个额外项目可能不是最新的(非常旧的代码)。
我自己在我的图书馆Time4J上工作,除了POSIX之外还有TAI,GPS和UTC支持。
[自2014年7月更新:Time4J现已作为稳定版本time4j-v1.0提供。这一争论已被考虑在内 - 例如参见Moment.toString(TimeScale) 。]
对OP新发布的问题进行更正和详细评论:
a)是的,即使在闰秒期间,TAI也以SI秒为单位单调增加。如果它只是你想要的东西你可能选择TAI,但是有一个陷阱。如果你想描述民用时间戳,那么TAI会给你错误的时间戳(只比较Wikipedia diagram的第一列和第二列)。原因很简单,民用生活由UTC统治,而不是TAI。
b)关于我的评论,维基百科的图表是错误的,我已经仔细查看了它并改变了主意。 POSIX和TAI之间的关系不固定(仅在1972年10s偏移),所以请原谅我的错误。到目前为止,我对TAI没有太多考虑,而是关于POSIX和UTC。但是感谢这个问题和这个充满启发性的辩论,所以你值得我的支持。整件事情很棘手。当我们谈论在不同时间尺度上表示的时间戳时,我们需要在ymdhms-form和epochsecs-form之间做出改变。让我们详细考虑一下1999-01-01T00:00:00Z(UTC-scale):
i) TAI = (29 * 365 + 7) days * 86400 + 22 leap seconds + 10s (offset at 1972) = 915148832
ii) UTC = TAI - 10 = 915148822 (fixed relation between UTC and TAI on epoch-second-level)
iii) POSIX = UTC - 22 leap seconds = 915148800
=> (ymdhms-form);
i) TAI (915148800 + 32) = 1999-01-01T00:00:32 (based on TAI-"day" = 86400 SI-secs)
ii) UTC = 1999-01-01T00:00:00 (stripped off former 22 leap secs in conversion to ymdhms)
iii) POSIX = 1999-01-01T00:00:00 (fixed relation between UTC and POSIX with exception of leapsecs)
那为什么TAI不算闰秒的说法呢?它不计算ymdhms形式的leapsecs,但当然它将它们计入第二级(单调性要求!)。和POSIX?它根本不计算闰秒,以ymdhms形式计算,也不计算在epoch-secs级别。所以最后我们在TAI和POSIX之间没有固定的关系。转换需要闰秒表。
c)POSIX规范讲述了闰秒行为?见here。特别注意声明:&#34;实际时间与自Epoch以来秒的当前值之间的关系未指定。&#34;所以这也关系到闰秒。如果它们在闰秒之前跳跃或者跳跃或者冻结一秒钟,则由时钟实现。
d)是的,System.currentTimeMillis()
将获得相当于POSIX时间(虽然以毫秒而非秒为单位)。
e)需要注意的是,标签TAI没有在1971年之前定义,国际原子时间也没有在1958年之前定义,所以三个额外级TAIInstant的预感规模在某种程度上是无稽之谈。所以我不会在1972年之前申请TAI。在这里,我选择时间尺度方面的专家Steve Allen。
f)如果你需要一个可以在JVM和机器上移植的时间对象&#34;然后UTC本身要求在任何地方分配/存在相同的闰秒表。如果选择TAI,则仍需要此闰秒表,以便应用程序能够将TAI时间戳转换为UTC或POSIX时间戳。所以我怀疑你可以有一个单调增加的时间戳并同时忽略闰秒。 TAI没有为这种困境提供解决方案。
2013-12-31对OP的问题/摘要的回答:
您对TAI和POSIX的摘要是正确的。
关于UTC,您首先应该明白UTC是一种妥协。一方面,它被设计为跟随太阳,另一方面,UTC标度上的第二个与TAI标度完全相同,即SI-second(原子定义)。当你说地球自转速度不可预测地减慢时,你是对的,所以插入闰秒几次。 UT1(平均太阳时)和UTC之间的差异应始终小于0.9 SI-seconds。因此,这个以及相等SI秒的事实是UTC的核心思想。另外,JSR-310中异乎寻常的UTC-SLS量表的改编与UTC的这些核心思想不兼容。关于闰秒的可预测性,巴黎的BIPM宣布每半年一次,如果6个月之后将会有一个闰秒或者没有,所以你有这个可预测性框架提前六个月。
关于UTC部分的一个可能是迂腐的修正,你写道:&#34;太阳总是在UTC时间中午处于最高位置。&#34;在类java.time.Instant的javadoc中也给出了类似的声明,关于所谓的java时标。撇开这个事实,你肯定不想说太阳的位置与你的本地位置无关,在中午的正确经度上它甚至都不正确。为什么?从天文学/科学的角度来看,你首先应该不要忘记平均太阳日照时间与你观看的真正的当地太阳时间不同(只是给出关键字&#34;时间等式&#34;)。此外,由于UTC仍然基于原子时间并使用原子时间进行同步,因此在UT1和UTC之间存在所谓的delta-T关系。这个delta在0.9secs的范围内,并由IERS / BIPM在公告B中定期发布。当你想要获得太阳的真实位置和太阳最高时,你需要知道这个三角洲。
&#34;代表时代&#34;在我看来有点太简单了。好的,我们可以说TAI和POSIX计算秒数,而UTC则以年/月/日/ ......形式表示。但我们确实可以将两种表示应用于所有尺度。但我们需要仔细区分这些表述并彻底思考如何转换。请注意,维基百科甚至在图表中为TAI选择了ymdhms格式。那么,计算机可以最好地存储简单的整数。 POSIX或TAI可以很容易地以这种格式存储。但正如我之前所说,对这些整数的解释并不总是那么简单。在TAI的情况下,你甚至需要一个闰秒表来转换为可读的民用ymdhms-form(UTC或POSIX)。
关于下一节&#34;翻译时间&#34;,我同意第1-3点。
您的最终陈述&#34;另一方面,很容易从POSIX转换为UTC&#39;人工解释&#39;。&#34;是正确的,除了闰秒。好吧,我用我即将到来的图书馆在不同尺度之间进行适当的翻译。它有一个内置但可配置的闰秒表,将来我还计划使用IANA-TZDB数据作为这样一个表的来源。
总而言之,大多数业务开发人员都不需要那么高的准确性。大多数人会简单地平衡POSIX和UTC,并且可能会对Linux OS或Google NTP服务器上的任何平滑硬件解决方案感到满意。真正的UTC和TAI(考虑到闰秒)需要更多的努力。因此,您必须确定您的软件架构是否需要科学准确性。
而且需要注意的是,JSR-310官方并没有完全解决范围非常广泛的POSIX,相反,他们说,他们的Instant类定义为UTC-SLS(另见这个有趣的debate)
最后,我对这次讨论很优雅。它还帮助我澄清了我对图书馆TAI的看法。感谢。