Java 8 LocalDateTime.now() 只给出毫秒精度

Java 8 LocalDateTime.now() only giving precision of milliseconds

是否可以在 Java 8 中获得微秒? Java 8 LocalDateTime class 有一个 .getNano() 方法,它意味着 return nanoseconds,但在 Linux(Ubuntu) 和 OS X (10.11.5) 它只有 returns milliseconds (当我 运行 它 returned 301000000 等于 301 milliseconds) 我真的需要能够得到 microseconds.

我知道可以在我的计算机上作为 javascript 方法 process.hrtime() return是一个精确的值。

在任何人开始精确与准确的争论之前,我知道纳秒在线程之间是完全不可靠的,不应该用于比较。

编辑:

需要明确的是,LocalDateTime class 是 Java 8 java.time 组 classes 的一部分。

更新:

所以我意识到 Java 脚本的 process.hrtime 就像 Java 的 System.nanoTime() 并且实际上与挂钟无关,是时候了两种语言之间不同的值。

新问题:有没有一种方法可以从这些值中解析出时钟时间? IE。如果我得到 System.currentTimeMillis()System.nanoTime(),并将其与另一组这些值进行比较,我可以获得第二组值的实际时间吗?

我的问题是我需要使用 Java 和 Java 脚本进行日志记录,并且它们需要在两者之间具有一致的微秒字段。

虽然您的计算机能够报告比毫秒更精确的东西(但可能不准确,至少在挂钟时间内不准确),但这不会改变 Java 默认使用 Clock 基于 System.currentTimeMillis().

你必须provide a more precise Clock to get values more precise than ms. That is,

LocalDate.now() 依赖于 SystemClock::instant() 方法,该方法使用 System.currentTimeMillis(),因此您无法使用默认时钟获得更精确的分辨率。

但是,您可以实现自己的高精度 Clock 并将其与 LocalDate 结合使用:

LocalDate hpDate = LocalDate.now(microsecondClock);

对于高精度,您可以使用带有微秒刻度的 TickClock

Clock microsecondClock = Clock.tick(Clock.systemUTC(), Duration.ofNanos(1000));

或子类 Clock 并实现您自己的高精度时钟,即通过使用 System.currentTimemillis() 和 System.nanoTime()。

tl;博士

Is it possible to get microseconds in Java 8?

不,不在 Java 8. 使用 Java 9 或更高版本。

Instant.now()  // Returns a value in microseconds in Java 9 and later, but is restricted to mere milliseconds in Java 8.

这是指 Java 8/9 的 Oracle 和 OpenJDK 实现。其他人可能会有所不同。

Java 9 及更高版本

Java 9 有一个 fresh implementation of java.time.Clock 能够以比毫秒更精细的分辨率( 位小数)捕获当前时刻。

实际分辨率取决于您的主机硬件时钟的限制。在带有 Oracle Java 9.0.4 的 macOS Sierra 上,我得到的当前时刻为微秒(6 位小数)。

Instant.now().toString()

2018-03-09T21:03:33.831515Z

Java 8

java.time classes 是 Java 8 中的新增内容。这些 classes 被定义为携带纳秒(nine 小数位数)。但是捕获当前时刻仅限于 milliseconds in Java 8, and enhanced in Java 9 to capture the current moment in finer microseconds.

2018-03-09T21:03:33.831Z

其他问题

System.currentTimeMillis()

If I get System.currentTimeMillis() and System.nanoTime()

无需再使用 System.currentTimeMillis()。而是使用 java.time.Instant 在 UTC 中使用精确到纳秒的分辨率。

如果您确实需要从 1970-01-01T00:00Z 的纪元参考开始计算毫秒数,请询问 Instant 对象。请注意数据丢失,因为您会忽略 Instant.

中存在的任何微秒或纳秒
long millisSinceEpoch = instant.now().toEpochMilli() ;

Is there a way that I can parse clock time from these values?

是的,您可以将自 1970-01-01T00:00Z 纪元以来的毫秒数转换为 Instant.

Instant instant = Instant.ofEpochMilli( millisSinceEpoch ) ;

System.nanoTime()

至于 System.nanoTime(),它用于跟踪经过的时间,例如对代码的性能进行基准测试。调用 System.nanoTime() 不会 告诉您有关当前 date-time.

的任何信息

此值是自某个未记录的原始时间点以来的纳秒计数。在实践中,我看到这个数字似乎在跟踪自 JVM 启动以来的时间,但这种行为没有记录,所以你不应该依赖它。

LocalDateTime 不是片刻

My problem is that I need to do logging using both Java and Javascript and they need to have a consistent microsecond field across both of them.

首先,对于日志记录,您应该而不是使用LocalDateTime class。 class 故意缺少任何时区或 offset-from-UTC 的概念。因此,LocalDateTime 不是代表一个时刻,不是时间轴上的一个点。 LocalDateTime 是关于 潜在 时刻的想法,范围约为 26-27 小时。仅当 zone/offset 未知(情况不好)时才使用 LocalDateTime,或者如果这表示类似于“圣诞节从 2018 年 12 月 25 日的第一刻开始”,其中圣诞节在不同时刻开始全球不同地区,从远东(太平洋)开始,连续午夜后向西移动。

对于日志记录,您应该使用 UTC。在 Java 中,这将是 Instant class,根据定义始终采用 UTC。只需调用 Instant.now().

当序列化为文本(例如用于日志记录)时,请始终使用标准 ISO 8601 格式。当 parsing/generating 字符串时,java.time classes 默认使用这些标准格式。您在本答案中看到了上面的示例。

参见另一个问题,

ISO 8601

在 ISO 8601 中,秒的小数可以有任意位数。所以你真的不应该关心记录的事件是以毫秒、微秒还是纳秒为单位记录的。

Instant instant = Instant.parse( "2018-03-09T21:03:33.123456789Z" ) ;
Instant instant = Instant.parse( "2018-03-09T21:03:33.123456Z" ) ;
Instant instant = Instant.parse( "2018-03-09T21:03:33.123Z" ) ;

截断

如果您真的认为您需要统一的分辨率,您可以truncate a Instant

Instant instant = Instant.now().truncatedTo( ChronoUnit.MILLIS ) ; // Strip away any microseconds or nanoseconds.

不用担心分辨率

My problem is that I need to do logging using both Java and Javascript and they need to have a consistent microsecond field across both of them.

首先,我怀疑你真的需要关心这个。如果您使用标准的 ISO 8601 格式,并且 Instant class 在 Java 中,您可以在毫秒、微米或纳米中成功地序列化和 re-hydrate 片刻。

即使小数秒分辨率不同,ISO 8601 格式的字符串也可以方便地按时间顺序排列。

其次,如果您出于某种原因试图将实际时刻跟踪到微秒级,您可能会失望。截至 2018 年,传统计算机时钟在微秒范围内并不可靠。


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

您可以直接与数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* classes。 Hibernate 5 和 JPA 2.2 支持 java.time.

从哪里获得 java.time classes?