InstantDateとLocalDateTimeの違いは何ですか?


256

そんなこと知ってる:

  • インスタントは、計算のための「技術的な」タイムスタンプ表現(ナノ秒)です。
  • LocalDateTimeは、人間のタイムゾーンを含む日付/時計の表現です。

結局のところ、IMOはどちらもほとんどのアプリケーションのユースケースで型として使用できます。例:現在、バッチジョブを実行していますが、日付に基づいて次の実行を計算する必要があり、これら2つのタイプ間の長所/短所を見つけるのに苦労しています(インスタントおよびタイムゾーン部分のナノ秒精度の利点は別として) LocalDateTimeの)。

InstantまたはLocalDateTimeのみを使用する必要があるアプリケーションの例を挙げてください。

編集:精度とタイムゾーンに関するLocalDateTimeの誤ったドキュメントに注意してください


インスタントはもっと基本的なもので、UTCの標準的なロングをラップしています。cronのようなバッチの場合、それほど論理的な選択ではありません。
Joop Eggen、2015

37
誤った定義。タイムゾーンがありLocalDateTimeませ
バジルブルク

回答:


831

モダンとレガシーの両方のJavaのすべての日時タイプの表

tl; dr

InstantそしてLocalDateTime2匹の全く異なる動物です:一つは瞬間を表し、他にはありません。

  • Instant タイムラインの特定の時点である瞬間を表します。
  • LocalDateTime日付と時刻を表します。しかし、タイムゾーンまたはUTCからのオフセットがないためこのクラス瞬間を表すことができません。世界中のすべてのタイムゾーンの範囲である約26〜27時間の範囲に沿った潜在的な瞬間を表します。

誤った推定

LocalDateTime 人間のタイムゾーンを含む日付/時計表現です。

ステートメントが正しくありませんA LocalDateTimeタイムゾーンがありません。タイムゾーンがないことは、そのクラスの全体のポイントです。

そのクラスのドキュメントを引用するには:

このクラスは、タイムゾーンを格納または表しません。代わりに、誕生日に使用される日付の説明と、壁掛け時計に表示される現地時間を組み合わせたものです。オフセットやタイムゾーンなどの追加情報がなければ、タイムライン上のインスタントを表すことはできません。

つまりLocal…、「ゾーン化されず、オフセットなし」を意味します。

Instant

ここに画像の説明を入力してください

An InstantUTCのタイムライン上の瞬間であり、1970 UTCの最初の瞬間のエポックからのナノ秒数です(基本的に、重要な詳細についてはクラスドキュメントを参照してください)。ビジネスロジック、データストレージ、およびデータ交換のほとんどはUTCで行う必要があるため、これは頻繁に使用される便利なクラスです。

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

OffsetDateTime

ここに画像の説明を入力してください

クラスOffsetDateTimeclassは、UTCの前後の時間数分秒のコンテキストで、瞬間を日時として表します。オフセットの量、時間、分、秒の数は、ZoneOffsetクラスによって表されます。

時間-分-秒の数がゼロの場合、OffsetDateTimeはUTCの瞬間を表し、Instantます。

ZoneOffset

ここに画像の説明を入力してください

このZoneOffsetクラスは、UTCからのオフセットまたはUTCからの時間数分秒の数である、UTCからのオフセットを表します。

ZoneOffsetは、時間、分、秒の数にすぎません。ゾーンははるかに多く、オフセットする名前と変更の履歴があります。したがって、ゾーンを使用することは、単なるオフセットを使用するよりも常に望ましい方法です。

ZoneId

ここに画像の説明を入力してください

タイムゾーンが表されZoneIdたクラス。

新しい日がパリの早い夜明けたとえば、はモントリオールよりも方ます。したがって、特定の地域の正午(太陽が真上にあるとき)をよりよく反映するように、時計の針を動かす必要があります。西ヨーロッパ/アフリカのUTCラインから東/西に離れるほど、オフセットが大きくなります。

タイムゾーンは、地域社会や地域で行われている調整や異常を処理するための一連のルールです。最も一般的な異常は、夏時間(DST)として知られている、あまりにも人気の高い狂気です。

タイムゾーンには、過去のルール、現在のルール、および近い将来に確認されるルールの履歴があります。

これらのルールは、予想よりも頻繁に変更されます。日時ライブラリのルール、通常は「tz」データベースのコピーを最新の状態に保つようにしてください。OracleがリリースするJava 8では、最新の状態を維持することが今までになく簡単になりました。 Timezone Updater Toolを

指定適切なタイムゾーン名をの形式でContinent/Region、のようなAmerica/MontrealAfrica/CasablancaまたはPacific/Auckland。決してなど2-4文字の略称を使用していないESTか、ISTそのままではない真の時間帯ではなく、標準化、さらには一意ではありません(!)。

タイムゾーン=オフセット+調整規則

ZoneId z = ZoneId.of( Africa/Tunis ) ; 

ZonedDateTime

ここに画像の説明を入力してください

ZonedDateTime概念的にはInstant、割り当てられたと考えてくださいZoneId

ZonedDateTime =(Instant + ZoneId)

特定の地域(タイムゾーン)の人々が使用する実時間で表示される現在の瞬間をキャプチャするには:

ZonedDateTime zdt = ZonedDateTime.now( z ) ;  // Pass a `ZoneId` object such as `ZoneId.of( "Europe/Paris" )`. 

バックエンド、データベース、ビジネスロジック、データの永続性、データ交換のほぼすべてがUTCである必要があります。ただし、ユーザーに提示する場合は、ユーザーが期待するタイムゾーンに調整する必要があります。これは、これらの日時値の文字列表現を生成するために使用されるZonedDateTimeクラスとフォーマッタクラスの目的です。

ZonedDateTime zdt = instant.atZone( z ) ;
String output = zdt.toString() ;                 // Standard ISO 8601 format.

を使用して、ローカライズされた形式でテキストを生成できますDateTimeFormatter

DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ; 
String outputFormatted = zdt.format( f ) ;

mardi 30 avril 2019à23 h 22 min 55 s heure de l'Inde

LocalDateLocalTimeLocalDateTime

<code> LocalDate </ code>のカレンダーのみを示す図。

<code> LocalTime </ code>のクロックのみを示す図。

<code> LocalDateTime </ code>のカレンダーと時計を示す図。

「ローカル」日時クラス、LocalDateTimeLocalDateLocalTime、生き物の異なる種類です。は、特定の地域やタイムゾーンに関連付けられていません。タイムラインとは関係ありません。それらを地域に適用してタイムライン上のポイントを見つけるまで、実際の意味はありません

これらのクラス名の「ローカル」という言葉は、初心者にはわかりにくいかもしれません。単語は、特定の場所ではなく任意の場所またはすべての場所を意味します

したがって、ビジネスアプリの場合、「ローカル」タイプは、タイムライン上の特定の瞬間ではなく、可能性のある日付または時刻の一般的な概念を表すだけなので、あまり使用されません。ビジネスアプリは、請求書が到着した瞬間、輸送のために出荷された製品、従業員が雇われた瞬間、またはタクシーがガレージを離れた瞬間を気にする傾向があります。そのためInstant、ビジネスアプリ開発者は、ZonedDateTime最もよく使用するクラスを使用しています。

では、いつ使用しLocalDateTimeますか?3つの状況:複数の場所に特定の日付と時刻を適用する場合、予定を予約する場合、または意図した未確定のタイムゾーンがある場合。これら3つのケースはいずれも、タイムライン上の特定の特定のポイントではなく、いずれも瞬間ではないことに注意してください。

1つの時刻、複数の瞬間

特定の日付の特定の時刻を表現したいが、タイムゾーン全体の複数の地域にそれを適用したい場合があります。

たとえば、「2015年12月25日の真夜中にクリスマスが始まる」はLocalDateTimeです。パリではモントリオールとは異なる瞬間に真夜中がストライキし、シアトルオークランドでもストライキが異なります。

LocalDate ld = LocalDate.of( 2018 , Month.DECEMBER , 25 ) ;
LocalTime lt = LocalTime.MIN ;   // 00:00:00
LocalTime ldt = LocalDateTime.of( ld , lt ) ;  // Xmas morning anywhere. 

別の例として、「Acme Companyは、世界中の各工場で昼休みが午後12時30分に始まるというポリシーを持っています」はLocalTimeです。本当の意味を持つためには、それをタイムラインに適用して、シュトゥットガルト工場で12:30、ラバト工場で12:30、またはシドニー工場で12:30の瞬間を把握する必要があります。

予約の予約

使用するもう1つの状況LocalDateTimeは、将来のイベントを予約する場合です(例:歯科医の予約)。これらの予定は、将来、政治家がタイムゾーンを再定義する危険を冒すのに十分遠い可能性があります。多くの場合、政治家は予告をほとんど与えないか、まったく警告さえしません。政治家の時計の使い方に関係なく「来年の1月23日午後3時」を意味する場合、瞬間を記録することはできません。その地域がサマータイムを採用または削除した場合、午後3時が午後2時または午後4時に変わることになります。例えば。

予定の場合は、a LocalDateTimeとa ZoneIdを別々に保管してください。後で、スケジュールLocalDateTime::atZone( ZoneId )を生成するZonedDateTimeときに、オブジェクトを生成するように呼び出して、その場で瞬間を決定します。

ZonedDateTime zdt = ldt.atZone( z ) ;  // Given a date, a time-of-day, and a time zone, determine a moment, a point on the timeline.

必要に応じて、UTCに調整できます。Instantからを抽出しZonedDateTimeます。

Instant instant = zdt.toInstant() ;  // Adjust from some zone to UTC. Same moment, same point on the timeline, different wall-clock time.

不明なゾーン

一部の人々はLocalDateTime、タイムゾーンまたはオフセットが不明な状況で使用する場合があります。

私はこの事件を不適切で賢明ではないと考えています。ゾーンまたはオフセットが意図されているが不明な場合、データが不良です。これは、意図する通貨を知らずに製品の価格を保存するようなものです。良い考えではありません。

すべての日時タイプ

完全を期すために、Javaでの最新のタイプとレガシーのタイプの両方、およびSQL標準で定義されているタイプのすべての可能な日時タイプの表を以下に示します。これは、InstantLocalDateTimeクラスをより大きなコンテキストに配置するのに役立ちます。

Javaのすべての日時タイプ(モダンとレガシーの両方)とSQL標準の表。

JDBC 4.2の設計においてJavaチームが行った奇妙な選択に注目してください。彼らはすべてのjava.time時間をサポートすることを選択しました。もっともよく使われる2つのクラスInstant&を除きZonedDateTimeます。

しかし、心配する必要はありません。簡単に前後に変換できます。

変換していInstantます。

// Storing
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject(  , odt ) ;

// Retrieving
OffsetDateTime odt = myResultSet.getObject(  , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;

変換していZonedDateTimeます。

// Storing
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject(  , odt ) ;

// Retrieving
OffsetDateTime odt = myResultSet.getObject(  , OffsetDateTime.class ) ;
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZone( z ) ; 

java.timeについて

java.timeのフレームワークは、Java 8に組み込まれており、後にされています。これらのクラスは面倒古い取って代わるレガシーのような日付時刻クラスをjava.util.DateCalendar、& SimpleDateFormat

ジョダタイムプロジェクトは、今でメンテナンスモードへの移行をアドバイスjava.timeのクラス。

詳細については、Oracleチュートリアルを参照してください。スタックオーバーフローで多くの例と説明を検索してください。仕様はJSR 310です。

java.timeオブジェクトをデータベースと直接交換することができます。に準拠したJDBCドライバーを使用するJDBC 4.2以降に。文字列もjava.sql.*クラスも必要ありません。

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

  • Java SE 8 Java SE 9 Java SE 10以降
    • 内蔵。
    • 実装がバンドルされた標準Java APIの一部。
    • Java 9では、いくつかのマイナーな機能と修正が追加されています。
  • Java SE 6および Java SE 7
    • java.time機能の多くはThreeTen-BackportでJava 6&7にバックポートされています。
  • アンドロイド
    • Androidの新しいバージョンには、java.timeクラスの実装がバンドルされています。
    • 以前のAndroid(<26)の場合、ThreeTenABPプロジェクトはThreeTen-Backport(上記)を採用しています。ThreeTenABPの使用方法…を参照してください。

JavaまたはAndroidのどのバージョンで使用するjava.timeライブラリの表

ThreeTen-エクストラプロジェクトでは、追加のクラスでjava.timeを拡張します。このプロジェクトは、java.timeに将来追加される可能性があることを証明する場です。あなたはここにいくつかの有用なクラスのような見つけることがIntervalYearWeekYearQuarter、および多くを


40
すばらしい答えです。Localネーミングのせいで少なくとも混乱が生じていると思います。以下のための私の直感Local私はどこに関連した意味し、私は(?!)、それが実際にどのようになると信じて私をリードZonedDateTimeです。
mkobit

4
はい、混乱しています。そのため、java.timeは、前作のJoda DateTime-Time(producing ZonedDateTime)が使用していたクラス名に「Zoned」という単語を巧みに追加して、「ローカル」クラスとの違いを強調しています。「ローカル」という名前は、「特定の地域に適用される必要性」の省略形と考えてください。
バジルブルク

2
単語を前に付けるLocalこともjava.utilパッケージと区別する方法であったかもしれませんが、どういうわけか私はより良い単語の選択があったかもしれないと感じています。
vphilipnyc 2016年

2
@simonhそれどころか…その新しい従業員が生命保険を含む彼らの利点を定義する彼/彼女の雇用書類に署名し、それからその新入社員がコーヒーだけのために外に出てトラックに命中させられ殺されたとき、そのような多くの人々がいるでしょう。人事部長、保険代理店、弁護士として、新しい雇用が発効した正確な瞬間を知りたいと思っています。
バジルブルク2017

2
@simonhはい、「ローカル」の日付時刻が適切な場合があります。私の回答で述べられているものに加えて、ビジネスでのもう1つの一般的なケースは、政治家がタイムゾーンのルールを変更する可能性があり、通常は予告なしに、2か月以上先に予定が作成される場合です。政治家はこれらの変更を頻繁に行います。たとえば、夏時間(DST)をオンまたはオフにするときに日付を変更したり、DSTを恒久的にオンまたはオフにしたままにします。
バジルブルク2017

20

主な違いの1つは、のLocal部分ですLocalDateTime。ドイツに住んでいてLocalDateTimeインスタンスを作成し、他の誰かが米国に住んでいて、同じ時刻に別のインスタンスを作成する場合(時計が正しく設定されている場合)-これらのオブジェクトの値は実際には異なります。これはInstant、タイムゾーンとは別に計算されるには適用されません。

LocalDateTimeタイムゾーンなしで日付と時刻を保存しますが、初期値はタイムゾーンに依存します。Instantのではありません。

さらに、LocalDateTime日、時間、月などの日付コンポーネントを操作するメソッドを提供します。ありInstantません。

Instantのナノ秒精度の利点とLocalDateTimeのタイムゾーン部分を除いて

両方のクラスの精度は同じです。LocalDateTimeタイムゾーンを保存しません。:あなたは、このような不正な仮定では大きなミスを犯す可能性があるため、徹底的にjavadocを読んでインスタントのLocalDateTime


ゾーン+精度の部分を読み違えて申し訳ありません。上記の投稿から繰り返して申し訳ありません:単一のタイムゾーンアプリケーションを考えます。どのユースケースでLocalDateTimeを優先するか、またはその逆ですか?
Manuel aldana

1
日付や時刻が必要なときはいつでもLocalDateTimeを使用します。時間、分などで。たとえば、インスタントを使用して実行時間を測定したり、時々発生するsthの内部フィールドを保存したりします。あなたの場合のように、次の実行を計算していますか?LocalDateTimeは適切に見えますが、それは意見です。おっしゃるように、どちらも使用できます。
Dariusz

さらに詳しく説明できますLocalDateTime stores date and time without timezone, but it's initial value is timezone dependentか?初期値とは何ですか?それはどのようにタイムゾーンに依存しますか?ありがとう。
最大

12

あなたは間違っていLocalDateTimeます:それはタイムゾーン情報を保存せず、ナノ秒の精度を持っています。Javadocの引用(私の強調):

ISO-8601カレンダーシステムでのタイムゾーンのない日時( 2007-12-03T10:15:30など)。

LocalDateTimeは、日時を表す不変の日時オブジェクトで、多くの場合、年、月、日、時、分、秒と表示されます。日、週、週など、その他の日付と時刻のフィールドにもアクセスできます。時間はナノ秒の精度で表されます。たとえば、値「2007年10月2日13:45.30.123456789」はLocalDateTimeに格納できます。

2つの違いは、Instantエポック(1970年1月1日)からのオフセットを表し、タイムライン上の特定の瞬間を表します。Instant地球の2つの異なる場所で同時に作成された2つのオブジェクトは、まったく同じ値になります。


単一のタイムゾーンアプリケーションを考えて、どのユースケースでLocalDateTimeを優先するか、またはその逆ですか?
Manuel aldana

3
@manuelaldanaそれは好みの問題です。ユーザー関連(誕生日...)にはLocalDateTimeを、マシン関連(実行時間...)にはInstantを好みます。
Tunaki、2015

2
@manuelaldana存在しないとしても、単一のタイムゾーンアプリはまれです。あなたは地元のバロック音楽クラブのために作り上げた小さなアプリのタイムゾーンを無視して逃げるかもしれません。しかし、旅行する(そしてタイムゾーンをまたぐ)ユーザーにイベントを投稿する必要があるとすぐに、そのデータをタイムゾーンに関連付けて、カレンダーアプリが必要に応じて調整できるようにします。すべてのアプリでタイムゾーンを適切に操作する方法を学ぶことをお勧めします。
バジルブルク

@Tunaki最後の段落で「オフセット」という言葉を使用すると、混乱が生じます。この単語は日時の作業で特定の意味を持つため、このコンテキストでの使用は役に立たない場合があります。
バジルブルク

0

Instant 本初子午線(グリニッジ)の時間に対応します。

一方LocalDateTime、OSのタイムゾーン設定に関連し、

オフセットやタイムゾーンなどの追加情報なしでインスタントを表すことはできません。


2
Instantは、GMTではなくUTCに基づいています。
Torsten Ojaperv
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.