tl;博士
在 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 和 java.time.Clock 能够以小于毫秒的分辨率捕获当前时刻(三位小数位)。
实际分辨率取决于主机硬件时钟的限制。在带有 Oracle Java 9.0.4 的 macOS Sierra 上,我得到了微秒的当前时刻(六 位小数)。
Instant.now().toString()
2018-03-09T21:03:33.831515Z
Java 8
java.time 类是 Java 8 中的新类。这些类被定义为携带纳秒(九 位十进制小数)。但捕获当前时刻仅限于 Java 8 中的 milliseconds,并在 Java 9 中增强以更精细地捕获当前时刻 microseconds。
2018-03-09T21:03:33.831Z
其他问题
System.currentTimeMillis()
如果我得到 System.currentTimeMillis() 和 System.nanoTime()
无需再使用System.currentTimeMillis()。而是在 UTC 中使用 java.time.Instant 片刻,分辨率可以达到纳秒级。
如果您确实需要从 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 类。该类故意缺少任何时区或与 UTC 偏移的概念。因此,LocalDateTime 确实不代表一个时刻,不是时间线上的一个点。 LocalDateTime 是关于在大约 26-27 小时范围内的潜在时刻的想法。仅当区域/偏移量未知(不是一个好情况),或者如果这表示“圣诞节从 2018 年 12 月 25 日的第一刻开始”之类的情况下使用 LocalDateTime,其中圣诞节在不同地区的不同时间开始地球,首先从远东(太平洋)开始,在连续的午夜之后向西移动。
对于日志记录,您应该使用 UTC。在 Java 中,这将是 Instant 类,根据定义始终使用 UTC。只需致电Instant.now()。
当序列化为文本(例如用于日志记录)时,请始终使用标准的ISO 8601 格式。 java.time 类在解析/生成字符串时默认使用这些标准格式。您在此答案中看到了上述示例。
查看另一个问题,What's the difference between Instant and LocalDateTime?。
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.
不用担心分辨率
我的问题是我需要同时使用 Java 和 Javascript 进行日志记录,并且它们需要在两者之间具有一致的微秒字段。
首先,我怀疑你真的需要关心这个。如果您使用标准 ISO 8601 格式和 Java 中的 Instant 类,您可以在毫秒、微米或纳米中成功地序列化和重新水化片刻。
即使小数秒分辨率不同,ISO 8601 格式的字符串也会方便地按时间顺序排列。
其次,如果您出于某种原因尝试将实际时刻跟踪到微秒,您可能会感到失望。截至 2018 年,传统的计算机时钟在微秒范围内并不可靠。
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。 Hibernate 5 & JPA 2.2 支持 java.time。
从哪里获取 java.time 类?