Java 8中是否可以获得微秒? Java 8 LocalDateTime
类有一个.getNano()
方法,它意味着返回nanoseconds
,但在Linux(Ubuntu)和OS X(10.11.5)上它只返回milliseconds
(当我运行它时它返回301000000
等于301 milliseconds
)并且我真的需要能够获得microseconds
。
我知道可以在我的计算机上获取nanoseconds
(因此可以从中获取microseconds
,因为javascript方法process.hrtime()
会返回一个精确的值。
在任何人开始精确与准确的论证之前,我知道线程之间的纳秒是完全不可靠的,不应该用于比较。
修改:
要清楚LocalDateTime
类是Java 8 java.time
类集的一部分。
更新:
所以我意识到Javascript的process.hrtime
就像Java的System.nanoTime()
,并且实际上并不与挂钟相关,因为它是两个语言之间不同的任意值的时间。
新问题:有没有办法可以解析这些值的时钟时间? IE浏览器。如果我得到System.currentTimeMillis()
和System.nanoTime()
,并将其与另一组值进行比较,我可以得到第二组值的实际时间吗?
我的问题是我需要使用Java和Javascript进行日志记录,并且需要在两者之间都有一致的微秒字段。
答案 0 :(得分:6)
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.
这指的是Oracle& Java 8/9的OpenJDK实现。其他可能不同。
Java 9的fresh implementation java.time.Clock
能够以超过毫秒(三位小数位数)的分辨率捕获当前时刻。
实际分辨率取决于主机硬件时钟的限制。在使用Oracle Java 9.0.4的macOS Sierra上,我得到当前时刻的微秒(六位小数位数)。
Instant.now().toString()
2018-03-09T21:03:33.831515Z
java.time类是Java 8中的新类。这些类被定义为携带纳秒(九位小数的数字)。但捕获当前时刻仅限于毫秒。
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小时之间。仅当区域/偏移未知(不是一个好的情况)时才使用LocalDateTime
,或者如果这表示类似于"圣诞节从2018年12月25日的第一时间开始,圣诞节开始于世界各地不同地区的不同时刻,首先在远东(太平洋)开始,并在午夜连续午夜后向西移动。
对于日志记录,您应该使用UTC。在Java中,这将是Instant
类,根据定义始终为UTC。只需致电Instant.now()
即可。
在序列化为日志等文本时,请始终使用标准ISO 8601格式。在解析/生成字符串时, java.time 类默认使用这些标准格式。您在本答案中看到了上述示例。
请参阅另一个问题What's the difference between Instant and LocalDateTime?。
在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 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 1 :(得分:2)
LocalDate.now()
依赖于使用SystemClock::instant()
的{{1}}方法,因此您无法使用默认时钟获得更精确的分辨率。
但是,您可以实现自己的高精度System.currentTimeMillis()
并将其与LocalDate结合使用:
Clock
对于高精度,您可以使用LocalDate hpDate = LocalDate.now(microsecondClock);
微秒刻度:
TickClock
或子类Clock microsecondClock = Clock.tick(Clock.systemUTC(), Duration.ofNanos(1000));
并实现您自己的高精度时钟,即使用System.currentTimemillis()和System.nanoTime()。
答案 2 :(得分:1)
虽然您的计算机能够报告更精确的内容(但可能不准确,至少不是在壁挂时间内),而不是毫秒,但这并不会改变Java默认使用基于{{Clock
的事实。 1}}。
您必须provide a more precise Clock
才能获得比ms更精确的值。也就是until Java 9。