从Epoch转换为millis到Java 10中的LocalDateTime转换为Java 8

问题描述 投票:3回答:1

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

这是Java 8中的输出

 ✘ 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)

这是Java 10中的输出,如果你看到格式是6位数字,而不是像Java 8中的那样,这打破了从Epoch到LocalDateTime的毫秒转换

✘ 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)

这是源代码

public class TimeTest{


public static void main(String[] args)
{

TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));

LocalDateTime issueTime = LocalDateTime.now();

System.out.println(issueTime.toString());

ZonedDateTime zdt = issueTime.atZone(TimeZone.getDefault().toZoneId());
long timeInMillis = zdt.toInstant().toEpochMilli();
System.out.println(timeInMillis );

LocalDateTime date = LocalDateTime.ofInstant(Instant.ofEpochMilli(timeInMillis), TimeZone.getDefault().toZoneId());

System.out.println(date.toString());
}
}

我如何在Java 10中解决这个问题?

java date java-8 java-10 localdate
1个回答
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()返回的实际值。

它在统计上不太可能,但绝对可能的是,它可以仅使用三个小数位而不是六位来表示。如果您的硬件支持,则更有可能需要9位小数而不是6位。当我在Java 10下运行你的代码时,通常会打印九个小数位,但偶尔只需要六个小数位。

其次,在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)将精度约束到三个小数位,但我没有看到这样做的好处,除非你有一个固定精度为三位小数的应用程序要求。另一种方法可能是使用纳米精度,如果需要,可以使用零填充到九位数;那么你将获得更高精度的好处,但仍然有固定的长度值。

© www.soinside.com 2019 - 2024. All rights reserved.