私はそれを知っています:
- インスタントは、むしろコンピューティングのための「技術的な」タイムスタンプ表現 (ナノ秒) です。
- LocalDateTime は、人間向けに
タイムゾーンを含む日付/時刻表現です 。
それでも、最終的には、ほとんどのアプリケーションの使用例では、どちらも型として捉えることができると私は考えています。例: 現在、日付に基づいて次の実行を計算する必要があるバッチ ジョブを実行しており、これら 2 つの型の長所と短所を見つけるのに苦労しています (のナノ秒精度の利点と のInstant
タイム ゾーン部分は別としてLocalDateTime
)。
Instant
またはのみLocalDateTime
を使用する必要があるアプリケーションの例をいくつか挙げてください。
編集:LocalDateTime
精度とタイムゾーンに関するドキュメントの誤読に注意してください。
ベストアンサー1
要約
Instant
これらはLocalDateTime
全く異なる 2 つの動物です。一方は瞬間を表し、もう一方はそうではありません。
Instant
瞬間、タイムライン内の特定のポイントを表します。LocalDateTime
日付と時刻を表します。ただし、タイムゾーンまたは UTC からのオフセットがないため、このクラスは瞬間を表すことができません。これは、世界中のすべてのタイムゾーンの範囲である約 26 ~ 27 時間の範囲に沿った潜在的な瞬間を表します。LocalDateTime
値は本質的に曖昧です。
誤った推定
LocalDateTime
むしろ、人間のためのタイムゾーンを含む日付/時刻の表現です。
あなたの記述は間違っています: ALocalDateTime
タイムゾーンがありません。タイムゾーンがないのがそのクラスのポイントです。
そのクラスのドキュメントを引用すると:
このクラスは、タイムゾーンを保存または表すものではありません。代わりに、誕生日に使用される日付の説明と、壁掛け時計に表示される現地時間を組み合わせたものです。オフセットやタイムゾーンなどの追加情報なしでは、タイムライン上の瞬間を表すことはできません。
つまり、Local…
「ゾーン分けなし、オフセットなし」という意味です。
Instant
アンInstant
タイムライン上の瞬間UTC、カウントナノ秒1970 UTC の最初の瞬間のエポックから (基本的に、詳細についてはクラス ドキュメントを参照してください)。ビジネス ロジック、データ ストレージ、およびデータ交換のほとんどは UTC で行う必要があるため、これは頻繁に使用する便利なクラスです。
Instant instant = Instant.now() ; // Capture the current moment in UTC.
OffsetDateTime
クラスOffsetDateTime
クラスは、UTCより何時間・分・秒進んでいるか遅れているかのコンテキストを持つ日付と時刻として瞬間を表します。オフセットの量、つまり何時間・分・秒の数は、ZoneOffset
クラス。
時間・分・秒の数がゼロの場合、OffsetDateTime
UTCの瞬間を表す。Instant
。
ZoneOffset
のZoneOffset
クラスはUTCからのオフセットUTC より進んでいる、または遅れている時間・分・秒数。
AZoneOffset
は単なる時間、分、秒の数値であり、それ以上のものではありません。ゾーンはそれ以上のものであり、名前とオフセットの変更履歴を持ちます。したがって、ゾーンを使用する方が、単なるオフセットを使用するよりも常に望ましいです。
ZoneId
新しい一日が早く明けるパリよりもモントリオール例えば、時計の針を動かして、よりよく反映させる必要があります。正午(太陽が真上にあるとき) 特定の地域におけるオフセット。西ヨーロッパ/アフリカの UTC ラインから東/西に離れるほど、オフセットは大きくなります。
タイムゾーンとは、地域社会や地域で実践されている調整や異常に対処するための一連のルールです。最も一般的な異常は、あまりにも一般的な狂気として知られているものです。夏時間 (DST)。
タイムゾーンには、過去のルール、現在のルール、近い将来に確定するルールの履歴があります。
これらのルールは予想以上に頻繁に変更されます。日付時刻ライブラリのルールは必ず保存しておいてください。通常は「tz」データベース、最新の状態に保つ。OracleがリリースしたJava 8では、最新の状態を維持するのがこれまで以上に簡単になりました。タイムゾーン更新ツール。
指定する適切なタイムゾーン名、、Continent/Region
またはなどの の形式で使用します。や などの 2 ~ 4 文字の略語は、実際のタイムゾーンではなく、標準化されておらず、一意でもありません(!)ので、使用しないでください。America/Montreal
Africa/Casablanca
Pacific/Auckland
EST
IST
タイムゾーン = オフセット + 調整ルール
ZoneId z = ZoneId.of( “Africa/Tunis” ) ;
ZonedDateTime
のことを考えるZonedDateTime
概念的には、 がInstant
割り当てられたとしてZoneId
。
ZonedDateTime = ( インスタント + ゾーン ID )
特定の地域 (タイムゾーン) の人々が使用する壁時計の時刻で現在の瞬間をキャプチャするには、次のようにします。
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 ) ;
2019年4月30日火曜日 23時22分55秒 インド
LocalDate
、、LocalTime
LocalDateTime
「ローカル」日付時刻クラス、LocalDateTime
、LocalDate
、LocalTime
は、異なる種類の生き物です。 は、特定の地域や時間帯に縛られていません。 タイムラインにも縛られていません。タイムライン上のポイントを見つけるために地域に適用するまで、それらは実際の意味を持ちません。
これらのクラス名にある「Local」という単語は、初心者には直感に反するかもしれません。この単語は、特定の地域ではなく、あらゆる地域を意味します。
そのため、ビジネス アプリでは、「ローカル」型はあまり使用されません。これは、これらの型がタイムライン上の特定の瞬間ではなく、考えられる日付や時刻の一般的な概念を表すだけだからです。ビジネス アプリでは、請求書が届いたとき、製品が輸送のために出荷されたとき、従業員が雇用されたとき、タクシーがガレージを出発したときなどの正確な瞬間が重要になる傾向があります。そのため、ビジネス アプリの開発者は、クラス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
LocalDateTime ldt = LocalDateTime.of( ld , lt ) ; // Christmas morning anywhere.
別の例として、「Acme社では、世界中の各工場で昼食時間は午後12時30分に始まるという方針をとっています」は、 ですLocalTime
。実際の意味を持たせるには、タイムラインに適用して、午後12時30分の瞬間を計算する必要があります。シュトゥットガルト工場または12:30ラバト工場または12:30シドニー工場。
予約
他にも、将来のイベントを予約する場合に使用できますLocalDateTime
(例: 歯医者の予約)。これらの予約は、政治家がタイムゾーンを再定義するリスクがあるほど遠い将来の可能性があります。政治家は事前の警告をほとんど与えないか、まったく警告しないことがよくあります。政治家が時計をどう操作するかに関係なく、「来年の 1 月 23 日午後 3 時」を意味している場合は、瞬間を記録することはできません。たとえば、その地域で夏時間が導入されたり廃止されたりすると、午後 3 時が午後 2 時または午後 4 時に変わる可能性があります。
予定については、LocalDateTime
と を別々に保存します。後でスケジュールを生成するときに、 を呼び出してオブジェクトを生成する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 標準で定義されているすべての日付と時刻型の表を以下に示します。これは、Instant
&LocalDateTime
クラスをより大きなコンテキストに配置するのに役立つ可能性があります。
Java チームが JDBC 4.2 の設計で行った奇妙な選択に注目してください。彼らは、最もよく使用される 2 つのクラス ( & )を除いて、すべてのjava.time時間をサポートすることを選択しました。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.Date
、Calendar
、&SimpleDateFormat
。
詳細については、Oracle チュートリアル. そして、Stack Overflowで多くの例と説明を検索してください。仕様はJSR310。
のジョダタイムプロジェクト、現在メンテナンスモード、への移行を勧めているjava.timeクラス。
java.timeオブジェクトをデータベースと直接交換することができます。JDBC ドライバー準拠JDBC 4.2以降。文字列もクラスも不要ですjava.sql.*
。Hibernate 5 と JPA 2.2 はjava.timeをサポートしています。
java.time クラスはどこで入手できますか?
- Java SE 8、Java SE 9、Java SE 10、Java SE 11以降 - バンドルされた実装を備えた標準 Java API の一部。
- Java9 についていくつかのマイナーな機能と修正を加えました。
- Java SE 6そしてJava SE 7
- java.timeの機能のほとんどはJava 6と7にバックポートされています。スリーテンバックポート。
- アンドロイド
- Android の新しいバージョン (26 以降) では、java.timeクラスの実装がバンドルされています。
- 以前のAndroid(<26)では、API脱糖もたらすjava.timeのサブセットAndroid に元々組み込まれていない機能。
- 脱糖で必要なものが得られない場合は、スリーテンABPプロジェクトは適応するスリーテンバックポート(上記)をAndroidにアップグレードします。ThreeTenABPの使い方…。
のスリーテンエクストラプロジェクトは、java.time に追加のクラスを追加して拡張します。このプロジェクトは、java.time に将来追加される可能性のある機能の実証の場です。ここでは、次のような便利なクラスが見つかるかもしれません。Interval
、YearWeek
、YearQuarter
、 そしてもっと。