简短概述
在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.
这指的是基于
OpenJDK开源代码实现的Java。其他可能会有所不同。
Java 9及以后版本基于OpenJDK实现,具有
全新的实现 java.time.Clock
,能够以比毫秒(
三位小数)更高的分辨率捕获当前时刻。
实际分辨率取决于主机计算机硬件时钟的限制。在macOS Sierra上使用Oracle Java 9.0.4,我得到的当前时刻是微秒级别的(
六位小数)。
Instant.now().toString()
2018-03-09T21:03:33.831515Z
Java 8
Java 8新增了java.time类。这些类被定义为可以容纳纳秒(小数点后九位)。但是在Java 8中,捕获当前时刻仅限于毫秒,在Java 9中得以提升,以更细的微秒精度捕获当前时刻。
2018-03-09T21:03:33.831Z
其他问题
System.currentTimeMillis()
如果我得到System.currentTimeMillis()和System.nanoTime(),以后就不需要再使用System.currentTimeMillis()了。相反,可以使用java.time.Instant获取UTC时刻,并具有纳秒级的分辨率。
如果确实需要从1970-01-01T00:00Z这个参考时刻开始计算毫秒数,请询问Instant对象。请注意数据丢失,因为您将忽略Instant中存在的任何微秒或纳秒。
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进行日志记录,并且它们需要具有一致的微秒字段。”
首先,对于日志记录,您不应该使用
LocalDateTime
类。该类故意缺乏任何时区或偏移量的概念。因此,
LocalDateTime
不表示一个瞬间,不是时间轴上的一个点。
LocalDateTime
是关于大约26-27小时范围内潜在时刻的想法。仅在时区/偏移量未知(不是很好的情况),或者如果这代表类似于“圣诞节从2018年12月25日的第一个时刻开始”,其中圣诞节在全球各地的不同区域的不同时刻开始,从太平洋地区向西逐渐推进,每个午夜后都会开始。
记录日志时应该使用UTC时间。在Java中,这将是
Instant类,根据定义始终为UTC。只需调用
Instant.now()
。
当序列化为文本(例如用于记录日志)时,始终使用标准的
ISO 8601格式。当解析/生成字符串时,
java.time类默认使用这些标准格式。在本答案中您可以看到示例。
请参见另一个问题,
Instant和LocalDateTime之间有什么区别?。
![Table of date-time types in Java, both modern and legacy](https://istack.dev59.com/u07Jj.webp)
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 = 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及以上版本内置的。这些类取代了老旧的legacy日期时间类,如java.util.Date
、Calendar
和SimpleDateFormat
。
要了解更多信息,请参见Oracle教程。并在Stack Overflow上搜索许多示例和解释。规范为JSR 310。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC驱动程序。无需字符串,无需java.sql.*
类。 Hibernate 5和JPA 2.2支持java.time。
如何获取java.time类?