【问题标题】:LocalDateTime.now() has different levels of precision on Windows and Mac machineLocalDateTime.now() 在 Windows 和 Mac 机器上具有不同级别的精度
【发布时间】:2018-08-26 20:15:12
【问题描述】:

在我的 Mac 和 Windows 机器上使用 LocalDateTime.now() 创建新的 LocalDateTime 时,我的 Mac 上的 nano 精度为 6,而 nano 精度为 3在我的 Windows 机器上。两者都在运行jdk-1.8.0-172

  • 是否可以限制或提高其中一个的精度 机器?
  • 为什么精度实际上不同?

【问题讨论】:

  • LocalDateTime.now() 使用system Clock,这意味着系统时钟的精度与LocalDateTime.now() 的精度相同。
  • "毫秒精度 6" 和微秒精度一样吗? (也许更好地表述为“亚秒级精度”)。
  • 对不起!它实际上被称为“纳米”。
  • @Slaw Running System.currentTimeMillis() 在两台机器上提供相同级别的精度。
  • 系统Clock 可以使用System.currentTimeMillis() 如果有更高分辨率的时钟。您的 Mac 似乎有一个精确到微秒的时钟。

标签: java precision java-time platform


【解决方案1】:

精度不同,因为LocalDateTime.now() 使用系统默认值Clock

从默认时区的系统时钟获取当前日期时间。

这将在默认时区查询system clock 以获取当前日期时间。

...

此 Javadoc 中的链接会将您带到 Clock.systemDefaultZone(),其中指出(强调我的):

获取一个使用最佳可用系统时钟返回当前时刻的时钟,使用默认时区转换为日期和时间。

此时钟基于最佳可用系统时钟。 这可能使用System.currentTimeMillis(),或者如果有更高分辨率的时钟可用。

...

Java 使用哪个时钟取决于很多事情,看起来您的 Mac 计算机的时钟精度为 micro 秒,而您的 Windows 计算机的时钟精度为 milli 秒精度。我不知道有什么方法可以提高时钟的精度,但您绝对可以降低精度,使其跨平台匹配。

一种选择是使用Ole V.V. does in his answer 并使用LocalDateTime.truncatedTo(TemporalUnit)

另一种选择是插入您自己的Clock 并使用LocalDateTime.now(Clock)。如果可能,我会使用Clock.tickMillis(ZoneId),因为此方法返回一个截断为毫秒的Clock

使用最佳可用系统时钟获取一个时钟,该时钟以整毫秒为单位返回当前即时滴答。

此时钟始终会将纳秒字段截断为毫秒。这确保了可见时间以整毫秒为单位。底层时钟是可用的最佳系统时钟,相当于使用system(ZoneId)。

...

自:
9

【讨论】:

  • 换句话说,当前时刻的分辨率是一个实现细节。
【解决方案2】:

我认为您无法获得比您已经获得的精度更高的精度。如果您想降低精度以匹配其他系统的精度,这很简单(当您知道如何操作时):

LocalDateTime.now(ZoneId.of("Europe/Berlin")).truncatedTo(ChronoUnit.MILLIS);

您获得的精度取决于硬件、设置、操作系统以及 JVM 与所有这些的集成。众所周知,Mac 通常比 Windows 提供更好的精度(尽管我的印象是 Java 9 中才有这种情况,根据 OpenJDK 问题 #JDK‑8068730)。

【讨论】:

  • 需要ZoneID吗?可能有点混乱,至少它隐藏了重要的部分(笔记本电脑)
  • 如果你想控制你得到的东西,这是一个好习惯,@CarlosHeuberger。如果你想要那个时候 JVM 的默认时区,我仍然更喜欢 ZoneId.systemDefault() 而不是忽略它。尽管结果相同,但它更清楚地阅读了意图。你是对的,这个讨论与所提出的问题无关。
  • 当然,有很多“好习惯”......喜欢这样的常数吗?喜欢避免太长的线条?
【解决方案3】:

如果有人对 Java 15 上的 macubuntu 上的 Instant 精度有同样的问题,我想展示一下区别:

mac 即时精度:2021-03-10T12:28:19.228816Z

ubuntu 即时精度:2021-03-10T12:28:19.228816800Z

解决方案:如果您想在此操作系统上获得相同的精度,请将.truncatedTo(ChronoUnit.MILLIS) 添加到Instant 变量

【讨论】:

    【解决方案4】:

    您可以使用格式化程序设置精度,而无需使用truncatedToClock.tickMillis

    jshell> OffsetDateTime.now().format(ISO_DATE_TIME)
    $5 ==> "2020-10-21T10:13:48.57776451+02:00"
    
    jshell> OffsetDateTime.now().format(ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSZ"))
    $8 ==> "2020-10-21T10:15:31.27+0200"
    

    我在发现JDK 15 has different precision on macOS and Linux之后才意识到这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-21
      • 1970-01-01
      • 2017-01-27
      • 1970-01-01
      • 2014-01-22
      • 1970-01-01
      相关资源
      最近更新 更多