2016-09-20 545 views
3

Java 8中可以获得微秒吗? Java 8 LocalDateTime类有一个.getNano()方法,这意味着返回nanoseconds,但在Linux(Ubuntu)和OS X(10.11.5)上它只返回milliseconds(当我运行它时,它返回301000000,这相当于301 milliseconds),我真的需要能够得到microsecondsJava 8 LocalDateTime.now()仅提供毫秒精度

我知道在我的计算机上有可能获得nanoseconds(因此得到microseconds),因为javascript方法process.hrtime()返回精确值。

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

编辑

要清楚的LocalDateTime类是Java 8 java.time组类的一部分。

更新

所以我意识到,JavaScript的process.hrtime就像Java的System.nanoTime(),并没有真正涉及到墙上的钟,它的时间,因为这是两种语言之间的一些不同的任意值。

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

我的问题是我需要使用Java和Javascript进行日志记录,他们需要在它们两个之间都有一致的微秒字段。

+0

http://stackoverflow.com/questions/33472569/any-new-method-to-get-current-time-with-accuracy-in-microseconds-in-java-now – Jens

+0

该帖子原本是从2009年和更新的答案是我遇到问题的解决方案。我正在寻找不同的东西。 – annedroiid

+0

https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#now--是最精确时间戳的最佳可用方法。 –

回答

2

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()。

+0

我将如何实现自己的时钟? – annedroiid

+0

class YourClock extends Clock {....}'...我假设有多种方法可以做到这一点,可以运行一个计时器线程,计算两次System.currentTimeMillis()形式的时间测量之间的循环迭代这会导出该间隔中的微秒或纳秒数。但请记住,你得到的越精确,它就越不准确。 –

+0

我需要使用micro/nano秒发送日志,这些日志也将与来自javascript项目的日志进行比较,因此我需要能够获得系统宽泛的微秒值。 – annedroiid

1

当您的计算机能够(在墙上的时间,但可能不准确的,至少不会)报告的东西更精确比毫秒,这并不能改变一个事实,每个默认的Java使用基于关闭的System.currentTimeMillis()一个Clock

您必须provide a more precise Clock才能获得比ms更精确的值。那就是until Java 9

1

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的OpenJDK实现。其他可能有所不同

的Java 9后来

的Java 9具有能够捕捉分辨率细当前时刻比毫秒(小数位数)的java.time.Clockfresh implementation一个。

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

Instant.now().toString() 

2018-03-09T21:03:33.831515Z

爪哇8

的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确实不是代表片刻,是而不是时间线上的一个点。 A LocalDateTime是关于潜在的时刻的想法,其沿着大约26-27小时的范围。仅当区域/偏移量未知(不是一种好的情况)时才使用LocalDateTime,或者如果这表示诸如“圣诞节从2018年12月25日的第一刻开始”,其中圣诞节开始于全球不同地区的不同时刻,首先从远东(太平洋)开始,然后在午夜后的午夜向西移动。

对于日志记录,您应该使用UTC。在Java中,这将是Instant类,按照定义始终以UTC表示。请致电Instant.now()

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

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做记录,他们需要跨两者一致微秒场。

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

即使分数秒分辨率变化,ISO 8601格式化字符串也会按照时间顺序排列。其次,如果您试图以某种原因追踪实际时刻为微秒,您很可能会感到失望。截至2018年,传统的计算机时钟在微秒范围内不可靠。


关于java.time

java.time框架是建立在Java 8和更高版本。这些类代替了日期时间类legacy,如java.util.Date,Calendar,& SimpleDateFormat

Joda-Time项目,现在在maintenance mode,建议迁移到java.time类。请参阅Oracle Tutorial。并搜索堆栈溢出了很多例子和解释。规格是JSR 310

您可以直接使用数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC driver。无需字符串,不需要java.sql.*类。

从何处获取java.time类?

ThreeTen-Extra项目与其他类扩展java.time。这个项目是未来可能增加java.time的一个试验场。您可以在这里找到一些有用的类,如Interval,YearWeek,YearQuartermore