web-dev-qa-db-ja.com

Java 8 LocalDateTime.now()はミリ秒の精度のみを提供します

Java 8でマイクロ秒を取得することは可能ですか?Java 8 LocalDateTimeクラスには.getNano()メソッドがあります。 nanosecondsを返すことを意味しますが、Linux(Ubuntu)とOS X(10.11.5)の両方で、millisecondsのみを返します(実行すると、_301000000_を返します。これは_301 milliseconds_)そして私は本当にmicrosecondsを取得できる必要があります。

Javascriptメソッドprocess.hrtime()が正確な値を返すので、コンピューターでnanosecondsを取得する(したがって、そこからmicrosecondsを取得する)ことが可能であることを知っています。

誰かが正確な議論を始める前に、ナノ秒はスレッド間で完全に信頼できないので、比較に使用すべきではないことを私は知っています。

編集

明確にするために、LocalDateTimeクラスはJava 8 _Java.time_クラスのセットの一部です。

更新

そのため、Javascriptの_process.hrtime_はJavaのSystem.nanoTime()に似ており、実際には掛け時計とは関係がないことに気付きました。2つの言語間で異なる任意の値があるためです。

新しい質問:これらの値から時計の時刻を解析する方法はありますか?つまり。 System.currentTimeMillis()System.nanoTime()を取得し、それをそれらの値の別のセットと比較すると、2番目の値のセットの実際の時間を取得できますか?

私の問題は、JavaとJavascriptの両方を使用してロギングを行う必要があり、両方で一貫したマイクロ秒フィールドが必要なことです。

8
annedroiid

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()を使用します。

4
Gerald Mücke

tl; dr

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の実装を指します。その他は異なる場合があります。

Java9以降

Java9には 新しい実装_Java.time.Clock_ ミリ秒よりも細かい解像度で現在の瞬間をキャプチャできます(three 小数の桁)。

実際の解像度は、ホストコンピューターのハードウェアクロックの制限によって異なります。 Oracle Java 9.0.4のmacOSSierraでは、マイクロ秒(6小数の桁)で現在の瞬間を取得しています。

_Instant.now().toString()
_

2018-03-09T21:03:33.831515Z

Java 8

Java.timeクラスはJava 8で新しく追加されました。これらのクラスはナノ秒(9小数の桁)を運ぶように定義されています。現在の瞬間のキャプチャは、 milliseconds in Java 8に制限され、現在の瞬間をより細かくキャプチャするためにJava 9で拡張されました。 マイクロ秒

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()を呼び出すと、notが現在の日時について何かを教えてくれます。

この値は、文書化されていないOriginの時点からのナノ秒数です。実際には、JVMが起動してからこの数値が時間を追跡しているように見えますが、この動作は文書化されていないため、信頼しないでください。

LocalDateTimenotちょっと

私の問題は、JavaとJavascriptの両方を使用してロギングを行う必要があり、両方で一貫したマイクロ秒フィールドが必要なことです。

まず、ロギングにはnotLocalDateTimeクラスを使用する必要があります。そのクラスには、タイムゾーンやUTCからのオフセットの概念が意図的に欠けています。そのため、LocalDateTimenotは瞬間を表し、notはタイムライン。 LocalDateTimeは、約26〜27時間の範囲に沿ったPotentialの瞬間についてのアイデアです。 LocalDateTimeは、ゾーン/オフセットが不明な場合(適切な状況ではない)、または「クリスマスの日は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

ISO 8601

ISO 8601では、1秒の小数部は任意の桁数にすることができます。したがって、ログに記録されたイベントがミリ秒、マイクロ秒、またはナノ秒のいずれで記録されたかを気にする必要はありません。

_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" ) ;
_

切り捨てる

really均一な解像度が必要だと思われる場合は、 Instant を切り捨てることができます。

_Instant instant = Instant.now().truncatedTo( ChronoUnit.MILLIS ) ; // Strip away any microseconds or nanoseconds.
_

解像度について心配する必要はありません

私の問題は、JavaとJavascriptの両方を使用してロギングを行う必要があり、両方で一貫したマイクロ秒フィールドが必要なことです。

まず、あなたが本当にこれを気にする必要があるのではないかと思います。標準のISO8601形式とJavaのInstantクラスを使用している場合は、ミリ秒、マイクロ、またはナノ単位で瞬間を正常にシリアル化および再水和できます。

また、ISO 8601形式の文字列は、秒単位の解像度が変化する場合でも、時系列でアルファベット順に並べることができます。

次に、何らかの理由で実際のモーメントをマイクロ秒単位で追跡しようとすると、がっかりする可能性があります。 2018年の時点で、従来のコンピュータークロックはマイクロ秒の範囲では信頼できません。


Java.timeについて

Java.time フレームワークはJava 8以降に組み込まれています。これらのクラスは厄介な古いクラスに取って代わります- legacy 日時クラス _Java.util.Date_Calendar 、& SimpleDateFormat

Joda-Time プロジェクトは、現在 メンテナンスモード であり、 Java.timeへの移行をアドバイスします。 クラス。

詳細については、 Oracle Tutorial を参照してください。そして、StackOverflowで多くの例と説明を検索してください。仕様は JSR 31 です。

Java.timeオブジェクトをデータベースと直接交換できます。 JDBC driverJDBC 4.2 以降に準拠しています。文字列は必要ありません。_Java.sql.*_クラスも必要ありません。

Java.timeクラスはどこで入手できますか?

ThreeTen-Extra プロジェクトは、追加のクラスでJava.timeを拡張します。このプロジェクトは、Java.timeに将来追加される可能性のある試験場です。 IntervalYearWeekYearQuarter などの便利なクラスがここにあります。 、および more

17
Basil Bourque

お使いのコンピュータはミリ秒よりも正確なものを報告できますが(ただし、少なくとも実時間では正確ではありません)、これによってJavaがデフォルトで使用されるという事実は変わりません ClockSystem.currentTimeMillis()に基づいています。

Msよりも正確な値を取得するには、 より正確なClock を指定する必要があります。つまり、 ntil Java 9

1
jensgram