Java 8 LocalDateTime.now() 只提供毫秒的精度tl;博士Java 9 及更高版本爪哇 8其他问题关于 java.time

2022-09-02 19:16:45

在Java 8中可以获得微秒数吗?Java 8类有一个旨在返回的方法,但是在Linux(Ubuntu)和OS X(10.11.5)上,它只返回(当我运行它时,它返回等于),我真的需要能够得到。LocalDateTime.getNano()nanosecondsmilliseconds301000000301 millisecondsmicroseconds

我知道有可能在我的计算机上获取(并因此从中获取),因为javascript方法返回一个精确的值。nanosecondsmicrosecondsprocess.hrtime()

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

编辑

需要明确的是,该类是 Java 8 类集的一部分。LocalDateTimejava.time

更新

所以我意识到Javascript就像Java一样,实际上与挂钟无关,现在是时候因为两种语言之间不同的一些任意值了。process.hrtimeSystem.nanoTime()

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

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


答案 1

tl;博士

在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 及更高版本

基于OpenJDK的Java 9的实现具有java.time.Clock的新实现,能够以比毫秒(小数点的三位数字)更精细的分辨率捕获当前时刻。

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

Instant.now().toString()

2018-03-19T10:03:33.831515Z

爪哇 8

java.time类是Java 8中的新类。这些类被定义为携带纳秒(十进制分数的位数字)。但是,在 Java 8 中,捕获当前时刻仅限于毫秒,在 Java 9 中则进行了增强,以更精细的微秒捕获当前时刻。

2018-03-19T10:03:33.831Z

其他问题

System.currentTimeMillis()

如果我得到System.currentTimeMillis() 和 System.nanoTime()

无需再使用。相反,在UTC中使用片刻,分辨率为纳秒。System.currentTimeMillis()java.time.Instant

如果您确实需要从 1970-01-01T00:00Z 的纪元引用中计算毫秒数,请询问对象。请注意数据丢失,因为您将忽略 中存在的任何微秒或纳秒。InstantInstant

long millisSinceEpoch = instant.now().toEpochMilli() ;

有没有办法从这些值中解析时钟时间?

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

Instant instant = Instant.ofEpochMilli( millisSinceEpoch ) ;

System.nanoTime()

至于 ,则用于跟踪经过的时间,例如对代码的性能进行基准测试。呼叫不会告诉您有关当前日期时间的任何信息。System.nanoTime()System.nanoTime()

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

LocalDateTime不是一瞬间

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

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

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

序列化为文本(如用于日志记录)时,请始终使用标准 ISO 8601 格式。默认情况下,java.time 类在解析/生成字符串时使用这些标准格式。你在这个答案中看到了上面的例子。

请参阅另一个问题,Instant 和 LocalDateTime 之间有什么区别?

Table of date-time types in Java, both modern and legacy

国际标准化组织 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" ) ;

截断

如果您真的认为自己需要统一的分辨率,则可以截断即时。

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

不用担心分辨率

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

首先,我怀疑你真的需要关心这一点。如果使用标准 ISO 8601 格式和 Java 中的类,则可以在毫微米、微米或纳米中成功地序列化和重新水合时刻。Instant

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

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


关于 java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧日期时间类,如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅 Oracle 教程。搜索 Stack Overflow 以获取许多示例和解释。规格是JSR 310

Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。

您可以直接与数据库交换 java.time 对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要类。Hibernate 5 & JPA 2.2 支持 java.timejava.sql.*

从哪里获取 java.time 类?


答案 2

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

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

LocalDate hpDate = LocalDate.now(microsecondClock);

对于高精度,您可以使用微秒刻度:TickClock

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

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


推荐