2015-11-02 47 views
66

一個用Java 8新的日期時間API的功能是應該納秒的精度。然而,當我打印出當前日期時間到控制檯,像這樣爲什麼新的Java 8 Date Time API不具有納秒精度?

DateTimeFormatter formatter = DateTimeFormatter 
    .ofPattern("yyyy-MM-dd'T'HH:mm:ss,nnnnnnnnnZ"); 
System.out.println(OffsetDateTime.now().format(formatter)); 

我只看到精確到毫秒:2015-11-02T12:33:26,746000000 + 0100

操作系統似乎支持納秒精度。當我通過終端

date -Ins 

打印當前日期時間我看到2015-11-02T12:33:26,746134417 + 0100

如何獲得納秒的精度在Java中?我在Ubuntu 14.04 64位

+1

彌補在Java中9. [A新鮮實施(https://開頭['Clock'](https://docs.oracle.com/javase/8/docs/api/java/time/Clock.html)的bugs.openjdk.java.net/browse/JDK-8068730)捕獲當前瞬間達到納秒分辨率(取決於主機硬件時鐘的能力)。 –

回答

101

一般java.time API不已經納秒的精度運行Oracle的Java 1.8.0_66。例如:

DateTimeFormatter formatter = DateTimeFormatter 
    .ofPattern("yyyy-MM-dd'T'HH:mm:ss,nnnnnnnnnZ"); 
OffsetDateTime odt = OffsetDateTime.of(2015, 11, 2, 12, 38, 0, 123456789, ZoneOffset.UTC); 
System.out.println(odt.format(formatter)); 

輸出:

2015-11-02T12:38:00,123456789+0000 

然而,這是它返回它只有毫秒的值由OffsetDateTime.now()返回的時鐘值。

從Java中8 Clock實現:

這裏提供的時鐘實現是基於System.currentTimeMillis()。該方法幾乎不保證時鐘的準確性。需要更準確時鐘的應用程序必須使用不同的外部時鐘(如NTP服務器)自行實現此抽象類。

所以沒有什麼內在的不精確性在這裏 - 使用System.currentTimeMillis()Clock只是默認的實現。你可能會創建你自己更精確的子類。但是,你要注意,添加更多的精度而無需添加更多精度可能不是非常有用。 (有些時候,它可能是,無可否認...)

+7

最後一點特別重要。 ['nanosleep(2)'](http://linux.die.net/man/2/nanosleep)在標準的消費級硬件上存在類似的問題,因爲睡眠準確的納秒數需要約1 CPU週期,這在搶先多任務的環境中是無法完成的。但是,如果您只需要訂購相互之間的各種事件並且不關心它們之間的精確時間間隔,那麼高級別的精度可能會很有用。我假設時鐘是單調遞增的,我希望*是真實的。 – Kevin

51

作出重要除了喬恩斯基特的答案,Java的9應該改進的精度提供時鐘 - 看到the bug log。背景:在許多操作系統(特別是Linux)上,有更好的時鐘可用。

爲java.time.Clock Java的SE 8規範規定:「 系統工廠方法基於現有的最佳
系統時鐘提供時鐘。這可以使用System.currentTimeMillis的(),或更高的 分辨率時鐘(如果有的話)「。在JDK 8的時鐘的
返回的實現是基於System.currentTimeMillis的(),並因此 僅具有一毫秒的分辨率。在JDK 9,實施
基於底層本地時鐘 System.currentTimeMillis的()被使用,從而提供可從該時鐘的最大分辨率 。在大多數系統中,這可能是微秒,即 或有時甚至是十分之一微秒。

作出假設,這些 系統工廠方法返回的時鐘永遠有毫秒的精度和 積極依賴於它,因此可能需要爲了進行更新,以 應用程序考慮到更高分辨率的可能性,正如API文檔中所述的

還應當指出,(外來)事實是第二精度將不存在近閏秒 - 甚至沒有在Java中9

+0

有更多關於閏秒附近不存在第二精度的信息嗎?那是因爲[有多種實現方法](https://en.wikipedia.org/wiki/Leap_second#Workarounds_for_leap_second_issues)(例如飛躍塗片)? – Thunderforge

+5

@Thunderforge像'ChronoUnit.SECONDS.between(instant1,instant2)'這樣的表達式永遠不會計算閏秒。 'java.time'-設計師決定隱藏閏秒並假裝每分鐘都包含60秒。他們的規範正式要求UTC-SLS,並且JDK中的真正實現與POSIX不同,實際上與UTC-SLS不同 - 簡單地忽略了閏秒。所有已知的操作系統時鐘(作爲'Clock.systemUTC()'的基礎)的行爲方式相同,或者應用某種時鐘重置或閏秒玷污的方式,SI-secs沒有被建模,如果你認真尋找真正的閏秒支持, lib Time4J。 –

相關問題