1. ホーム

[解決済み】InstantとLocalDateTimeの違いは何ですか?

2022-04-14 04:03:37

質問

それは知っています。

  • インスタント は、むしろコンピューティングのための技術的なタイムスタンプ表現(ナノ秒)である。
  • ローカル日付時間 は、むしろ人間のためのタイムゾーンを含む日付/時計表現です。

しかし、最終的には、ほとんどのアプリケーションのユースケースで、どちらも型として捉えることができると思います。例として 現在、私は日付に基づいて次の実行を計算する必要があるバッチジョブを実行しており、私はこれらの2つのタイプの長所/短所を見つけるのに苦労しています(Instantのナノ秒精度の利点とLocalDateTimeのタイムゾーンの部分を除いて)。

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

編集:精度やタイムゾーンに関するLocalDateTimeのドキュメントを読み違えないように注意してください。

解決方法は?

tl;dr

InstantLocalDateTime は全く別のものです。一方は瞬間を表し、他方は表さない。

  • Instant は、瞬間、つまりタイムライン上の特定のポイントを表します。
  • LocalDateTime は日付と時刻を表します。しかし、タイムゾーンやoffset-from-UTCがない。 このクラス はできません。 一瞬を表す . それは ポテンシャル これは地球上のすべてのタイムゾーンの範囲である約26時間から27時間の範囲にある瞬間です。A LocalDateTime の値は 本質的にあいまい .

不正確な推定

LocalDateTime は、むしろ人間のためのタイムゾーンを含む日付/時計表現です。

あなたの発言は間違っています。 A LocalDateTime があります。 いいえ 時間帯 . タイムゾーンを持たないというのは、そのクラスのすべてのポイントです。

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

このクラスはタイムゾーンを保存したり表現したりしない。その代わり、誕生日に使われるような日付と、壁掛け時計で見られるような現地時刻を組み合わせた記述になっています。オフセットやタイムゾーンなどの追加情報なしに、時間軸上のある瞬間を表すことはできません。

そこで Local… は「ゾーニングされていない、オフセットがない」という意味です。

Instant

An Instant は、タイムライン上のある瞬間を UTC のカウントは ナノ秒 1970 UTCの最初の瞬間のエポックから (基本的に、細かいことはクラスドキュメントを参照してください)。ビジネスロジック、データの保存、データ交換のほとんどはUTCであるべきなので、これは頻繁に使用される便利なクラスです。

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

OffsetDateTime

クラス OffsetDateTime クラスは、UTCから何時間・何分・何秒進んだか、あるいは遅れたかというコンテキストで、瞬間を日付と時刻で表します。オフセットの量、つまり時間-分-秒の数を表すのが ZoneOffset クラスがあります。

時間-分-秒の数が0の場合は OffsetDateTime は、UTC における瞬間を表します。 Instant .

ZoneOffset

ZoneOffset クラスは オフセットフロムUTC UTCから何時間・何分・何秒進んでいるか、またはUTCから何秒遅れているかを表します。

A ZoneOffset は、単に時間-分-秒の数であり、それ以上ではありません。ゾーンは、名前とオフセットの変更履歴を持ち、それ以上のものです。したがって、ゾーンを使用することは、単なるオフセットを使用するよりも常に望ましいことです。

ZoneId

A 時間帯 ZoneId クラスがあります。

で新しい一日が早くも幕を開ける。 パリ よりも モントリオール といった具合に。そこで、時計の針を動かして、より正確に 正午 (太陽が真上にあるとき)の地域があります。西ヨーロッパ/アフリカでUTCラインから東/西に離れるほど、オフセットは大きくなります。

タイムゾーンとは、地域やコミュニティで実践されている調整や異常の処理のためのルールのことです。最も一般的な異常は、次のように知られているあまりにも一般的な狂気です。 夏時間(DST) .

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

これらのルールは予想以上に頻繁に変更されます。必ず日付時刻ライブラリのルール、通常は tz'データベース を最新の状態に更新してください。Java 8 では Oracle が タイムゾーンアップデートツール .

を指定します。 適切なタイムゾーン名 のフォーマットで Continent/Region というように America/Montreal , Africa/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 クラスと フォーマッタクラス は、これらの日付-時刻値の String 表現を生成するために使用されます。

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

LocalDate , LocalTime , LocalDateTime

日付時刻のクラスです。 LocalDateTime , LocalDate , LocalTime とは、また別の種類の生き物です。特定の地域や時間帯に縛られることはありません。時間軸に縛られることもありません。 本当の意味はない タイムライン上のある地点に適用するまでは。

これらのクラス名に含まれる「Local」という単語は、知らない人にとっては直感に反するかもしれません。この単語の意味は 任意の 地域、または すべての の地域がありますが ではなく 特定のロケール

そのため、ビジネスアプリケーションでは、quot;Local" タイプは、タイムライン上の特定の瞬間ではなく、考えられる日付や時間の一般的なアイデアを表すだけなので、あまり使用されないようです。ビジネスアプリケーションでは、請求書が届いた瞬間、製品が輸送のために出荷された瞬間、従業員が雇われた瞬間、タクシーが車庫を出た瞬間など、正確な時間を気にする傾向があります。そのため、ビジネスアプリの開発者は InstantZonedDateTime クラスが最も一般的です。

では、どのような場合に LocalDateTime ? 3つのシチュエーションで

  • ある日付と時間帯を複数の拠点にまたがって適用したい。
  • アポイントメントを予約しています。
  • 時間帯は未定です。

これらの3つのケースは、いずれもタイムライン上のある特定の一点に関わるものではなく、瞬間的なものではないことに注意してください。

一つの時間帯、複数の瞬間

ある日のある時刻を表現したいが、それをタイムゾーンをまたいで複数の地域に適用したい場合がある。

例えば、"Christmas starts at midnight on 25th of December 2015"は、以下のようになります。 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 Companyは、世界中の各工場でランチタイムは午後12時30分に始まるというポリシーを持っている"は、次のようになります。 LocalTime . の12:30という瞬間を把握するために、タイムラインに適用する必要があります。 シュトゥットガルト 工場で12:30、あるいは ラバト 工場で12:30 シドニー の工場で行われます。

アポイントメントを予約する

もう一つの使用例 LocalDateTime は、将来のイベント(例:歯医者の予約)を予約する場合です。これらの予約は政治家がタイムゾーンを再定義する危険を冒すほど遠い将来であるかもしれません。政治家はしばしば、ほとんど予告をしないか、あるいはまったく予告しないこともあります。もしあなたが「来年1月23日の午後3時」という意味であれば、政治家がどのように時計を操作しようとも、午後3時が午後2時になったり、午後4時になったりする瞬間を記録することはできません。

予定については LocalDateTimeZoneId は、別々に保管されます。後で、スケジュールを生成するときに、その場で 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 クラスをより大きなコンテクストで表示します。

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.Date , Calendar , & SimpleDateFormat .

さらに詳しく知りたい方は オラクルチュートリアル . また、Stack Overflowで検索すると、多くの例や解説が見つかります。仕様書は JSR 310 .

ジョダタイム プロジェクトは、現在 メンテナンスモード への移行を推奨しています。 Java.time クラスがあります。

を交換することができます。 java.time オブジェクトを直接データベースとやり取りすることができます。データベースと直接接続するには JDBCドライバ に準拠した JDBC 4.2 またはそれ以降であること。文字列は必要ありません。 java.sql.* クラスがあります。Hibernate 5 & JPA 2.2サポート java.time .

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

スリーテン・エキストラ プロジェクトは、java.time を追加クラスで拡張します。このプロジェクトは、将来java.timeに追加される可能性のあるもののための実験場です。ここには、次のような便利なクラスがあります。 Interval , YearWeek , YearQuarter および もっと .