デフォルトでブラジルのタイムゾーンを使用していますが、ニューヨークのLocalDateTimeを1つキャッチしてJava.tim.Instantに変換すると、instantが正しく入力されます。問題は、ニューヨークのdateを生成する代わりにDate.from(instantValue)でDateを生成しようとするとブラジルから現在の日付を取得することになります。
ZoneId nyZone = ZoneId.of("America/New_York");
ZoneId brazilZone = ZoneId.of("America/Recife");
LocalDateTime ldtBrazil = LocalDateTime.now(brazilZone);
LocalDateTime ldtNY = LocalDateTime.now(nyZone);
Instant instantBrazil = ldtBrazil.toInstant(ZoneOffset.UTC);
Instant instantNY = ldtNY.toInstant(ZoneOffset.UTC);
System.out.println("-------LocalDateTime-------");
System.out.println("ldtBrazil : "+ldtBrazil);
System.out.println("ldtNY : "+ldtNY);
System.out.println("\n-------Instant-------");
System.out.println("instantBrazil: "+instantBrazil);
System.out.println("instantNY : "+instantNY);
long milliBrazil = instantBrazil.toEpochMilli();
long milliNY = instantNY.toEpochMilli();
System.out.println("\n----------Milli----------");
System.out.println("miliBrazil : "+milliBrazil);
System.out.println("miliNY : "+milliNY);
Date dateBrazil = Date.from(instantBrazil);
Date dateNY = Date.from(instantNY);
System.out.println("\n---------Date From Instant---------");
System.out.println("dateBrazil: "+dateBrazil);
System.out.println("dateNY : "+dateNY);
System.out.println("\n---------Date From Milli---------");
System.out.println("dateBrazil: "+new Date(milliBrazil));
System.out.println("dateNY : "+new Date(milliNY));
結果
-------LocalDateTime-------
ldtBrazil : 2016-09-21T22:11:52.118
ldtNY : 2016-09-21T21:11:52.118
-------Instant-------
instantBrazil: 2016-09-21T22:11:52.118Z
instantNY : 2016-09-21T21:11:52.118Z
----------Milli----------
miliBrazil : 1474495912118
miliNY : 1474492312118
---------Date From Instant---------
dateBrazil: Wed Sep 21 19:11:52 BRT 2016
dateNY : Wed Sep 21 18:11:52 BRT 2016 //this data must be related to NY LocalDateTime, but reiceved a same date of Brazil.
---------Date From Milli---------
dateBrazil: Wed Sep 21 19:11:52 BRT 2016
dateNY : Wed Sep 21 18:11:52 BRT 2016
LocalDateTime
はゾーンなしを意味しますLocalDateTime
の目的を誤解しているようです。
このクラスにはタイムゾーンも TCからのオフセット もありません。それはnotタイムライン上のポイントです。むしろ、可能性のある瞬間についてのあいまいな考えを表しています。 「Local…」という名前は、notが特定の地域を表すのではなく、直感的ではないかもしれませんが、anyの地域を表します。
たとえば、今年のクリスマスは、2016年12月25日の午前0時、または2016-12-25T00:00
です。タイムゾーンを適用して、オークランドNZまたはコルカタINまたはパリFRまたはモントリオールCAでクリスマスを迎えるまで、意味はありません。
LocalDateTime
を使用しないでください。ゾーンとオフセットの手間が省けると思うからです。それとは逆に、あいまいな日時値のある穴を掘り下げます。
ほとんどのビジネスロジック、ロギング、データストレージ、およびデータ交換はすべて [〜#〜] utc [〜#〜] にある必要があります。 UTCを1つの真の時間と考えてください。他のすべてのゾーンとオフセットは、ドレスアップされたUTC値を装います。
Java.timeでは、Instant
クラスがgo-toクラスであり、日時オブジェクトの基本的なビルディングブロックです。 Instant
クラスは、 [〜#〜] utc [〜#〜] のタイムライン上の瞬間を nanoseconds の解像度で表します。
Instant now = Instant.now();
ZonedDateTime
一部の地域の 壁時計時間 にアクセスする必要がある場合にのみ、タイムゾーンに調整します。 ZoneId
を適用して、ZonedDateTime
オブジェクトを取得します。
ZoneId zNewYork = ZoneId.of("America/New_York");
ZoneId zRecife = ZoneId.of("America/Recife");
ZonedDateTime zdtNewYork = now.atZone( zNewYork );
ZonedDateTime zdtRecife = now.atZone( zRecife );
これら3つのオブジェクト、now
、zdtNewYork
、およびzdtRecife
はすべてすべての瞬間、タイムライン上の同じ同時ポイントです。3つすべてが同じエポックからのカウントを共有しています。唯一の違いはレンズスルーです時計の時刻が表示されます。
最も古いバージョンのJavaにバンドルされている面倒な古い日時クラスの使用は避けてください。したがって、Java.util.Date
とJava.util.Calendar
は避けてください。彼らは本当に悪いです。 Java.timeクラスに固執します。
Java.time型用にまだ更新されていない古いコードを操作する必要がある場合は、Java.time型との間で変換できます。古いクラスに追加された新しいメソッドを探します。 Java.util.Date.from
メソッドはInstant
を取ります。 Instant
またはZoneDateTime
)からOffsetDateTime
を抽出できます。
Java.util.Date utilDate = Java.util.Date.from( zdtNewYork.toInstant() );
そして、他の方向に向かっています。
Instant instant = utilDate.toInstant();
変換の詳細については、 my Answer を質問に、 Java.util.Dateを「Java.time」型に変換しますか? を参照してください。
UTCで1970年のミリ秒などのエポックからのカウント数の使用は避けてください。カウントに使用されるさまざまな粒度(ミリ秒、マイクロ秒、ナノ秒、整数秒など)があります。 1970年以外にもさまざまなコンピューターシステムで使用されているエポックが少なくとも数十あります。数字は人間が読むと意味がないため、バグが検出されない可能性があります。
練習するときに役立つかもしれません。 getEpochSecond
でgetNano
およびInstant
を呼び出すか、切り捨てられた値の場合はtoEpochMilli
を呼び出します。
Java.time フレームワークは、Java 8以降に組み込まれています。これらのクラスは、面倒な古い legacy date-timeクラスに取って代わります。 Java.util.Date
、 Calendar
、および SimpleDateFormat
として。
Joda-Time プロジェクトは、現在 メンテナンスモード であり、 Java.time クラスへの移行を推奨しています。
詳細については、 Oracle Tutorial を参照してください。また、Stack Overflowで多くの例と説明を検索してください。指定は JSR 31 です。
Java.timeオブジェクトをデータベースと直接交換できます。 JDBC 4.2 以降に準拠する JDBCドライバー を使用します。文字列もJava.sql.*
クラスも必要ありません。
Java.timeクラスはどこで入手できますか?
_(ThreeTen-Extra プロジェクトは、追加のクラスでJava.timeを拡張します。このプロジェクトは、Java.timeに将来追加される可能性のある証明の場です。 Interval
、 YearWeek
、 YearQuarter
、および more 。
LocalDateTime
とInstant
(またはDate
の違いについて混乱しているように思えますが、これは本質的にInstant
)。これらは完全に異なるオブジェクトです。
LocalDateTime
は、特定のカレンダー日付と特定の時刻です。この絵のように考えることができます。
または、年、月、日、時間、分、秒と考えることができます。ただし、タイムゾーンはありません。それはまさにカレンダーの言うこと、時計の言うことです。
Instant
は瞬間です。たとえば、ニール・アームストロングが最初に月を踏んだ瞬間は、Instant
として表すことができます。 JFKが撃たれた瞬間もそうでした。
繰り返しますが、タイムゾーンはありません。しかし、それはLocalDateTime
とは異なるものです。どのタイムゾーンを書き留めるのかわからない限り、Instant
の時間を書き留めることはできません。ああ、そしてDate
はInstant
と同じものです。
したがって、LocalDateTime
とInstant
の間で変換するには、特定のタイムゾーンを参照する必要があります。ニール・アームストロングが月を踏んだ瞬間を年、月、日、時、分、秒として表現するために;使用するタイムゾーンを知る必要があります。 UTCを使用する場合、1969年7月21日の午前2時56分です。太平洋標準時を使用する場合、1969年7月20日の午後6時56分です。
その知識を武器に、コードを分析しましょう。いくつかのLocalDateTime
オブジェクトから始めました。
次に、UTCを使用してこれらをInstant
オブジェクトに変換します。
次に、これらを印刷します。これを行うにはタイムゾーンを知る必要がありますが、それでも構いません。 Instant
は、何があってもUTCで出力されます。それがZ
の意味です。
ここで、Instant
オブジェクトをミリ秒数に変換します。いいよこれは、UTC 1970年1月1日の午前0時からのミリ秒数です。 milliNYは、1時間前のInstant
に対応するため、milliBrazilよりも明らかに360万少ないです。
次に、Instant
オブジェクトをDate
オブジェクトに変換します。 Date
とInstant
は同じように表示されますが、印刷方法は異なりますが、実際には何も変わりません。
変換されたDate
オブジェクトを印刷します。それはあなたのロケールだからです。 dateNY
がdateBrazil
より1時間早いということはたまたま起こります。ただし、どちらもブラジル時間で印刷されます。これはUTCから3時間遅れています。したがって、それぞれ19:11:52と18:11:52になります。
最後に、ミリ秒単位の数からさらにDate
オブジェクトを作成します。ただし、これらの新しいDate
オブジェクトは、同じミリ秒数で作成したため、すでにあるdateBrazil
およびdateNY
とまったく同じです。そして再び、彼らはブラジルの時間に印刷されます。