从Epoch以来的millis转换为Java 10 vs Java 8中的LocalDateTime

时间:2018-09-07 03:42:29

标签: java date java-8 java-10 localdate

我有一个应用程序,自从Epoch转换到LocalDateTime以来,我使用毫秒,然后返回,该应用程序在Java 8上运行良好,但我尝试更新到Java 10,发现了以下问题

这是Java 8的输出

settings > Editor > File and Code Templates > Includes >

这是Java 10的输出,如果您看到格式的结尾是6位数字,而不是Java 8中的3位,这会中断从Epoch到LocalDateTime的毫秒转换

 ✘ magg@MacBook-Pro-de-Miguel  ~/Desktop/CODE  java TimeTest
2018-09-06T20:13:30.253
1536290010253
2018-09-06T20:13:30.253
 ✘ magg@MacBook-Pro-de-Miguel  ~/Desktop/CODE  java -version
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

这是源代码

✘ magg@MacBook-Pro-de-Miguel  ~/Desktop/CODE  java TimeTest
2018-09-06T20:13:18.568414
1536289998568
2018-09-06T20:13:18.568
 ✘ magg@MacBook-Pro-de-Miguel  ~/Desktop/CODE  java -version
java version "10.0.2" 2018-07-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.2+13)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.2+13, mixed mode)

如何在Java 10中解决此问题?

1 个答案:

答案 0 :(得分:8)

首先,LocalDateTime.toString()的输出长度不固定。从其Javadoc(从8到10不变):

public String toString()
Outputs this date-time as a String, such as 2007-12-03T10:15:30.
The output will be one of the following ISO-8601 formats:

uuuu-MM-dd'T'HH:mm
uuuu-MM-dd'T'HH:mm:ss
uuuu-MM-dd'T'HH:mm:ss.SSS
uuuu-MM-dd'T'HH:mm:ss.SSSSSS
uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS
The format used will be the shortest that outputs the full value of the time where the omitted parts are implied to be zero.

您的Java 10运行碰巧将秒值打印为小数点后六位,但是它可能已经打印了三位小数点或后九位小数点,具体取决于几个因素:

  • 计算机时钟,可能具有或不具有纳米精度。
  • now()返回的实际值。

从统计学上讲,它不可能只用小数点后三位而不是六位来表示,但绝对有可能。如果您的硬件支持的话,很有可能需要九位小数而不是六位。当我在Java 10下运行您的代码时,通常会打印9个小数位,但有时只需要6个小数位。

第二,在Java 9中,“ java.time.Clock返回的系统时钟”被更改为”,以便它们提供的精度至少与系统上可用的基础时钟相同。 “ 。请参阅JDK-8068730 Increase the precision of the implementation of java.time.Clock.systemUTC(),其中明确说明了您的情况:

  

一个应用程序假设这些时钟返回的时钟   系统工厂方法将始终具有毫秒精度,并且   积极地依赖它,因此可能需要更新才能   考虑到更大分辨率的可能性...

关于您的问题“如何在Java 10中解决此问题?” ,我不确定您要修复的问题,因为我不知道您应用程序的详细信息要求。

teppic 的评论已经说明了如何使用LocalDateTime.now().truncatedTo(ChronoUnit.MILLIS)将精度限制在小数点后三位,但是除非您拥有应用程序,否则我看不出这样做的好处要求固定精度为小数点后三位。一种替代方法是使用纳米精度,如果必要,将零填充到九位数。那么您将获得更高的精度,但仍具有固定的长度值。