予定の種類によって異なります。
予定には2種類あります:
- タイムゾーンルールの変更を無視した、タイムライン上の特定の時点。
例:ロケットの打ち上げ。 - タイムゾーンルールの変更に合わせて調整する必要がある日時。
例:医療/歯科訪問。
瞬間
たとえば、ロケットの打ち上げを予約する場合、日付と時刻は関係ありません。私たちは、(a)天が整列し、(b)好天を期待する瞬間だけを気にします。
その間に政治家が私たちの打ち上げサイトまたは私たちのオフィスで使用されているタイムゾーンのルールを変更した場合、それは私たちの打ち上げの予定に影響を与えません。ローンチサイトを管理している政治家が
そのような約束については、はい、あなたのアプローチは正しいでしょう。予定はTIMESTAMP WITH TIME ZONE
の列を使用する 。検索時に、ユーザーが希望する任意のタイムゾーンに調整します。
Postgres
などのデータベース 入力に付随する任意のタイムゾーン情報を使用してUTCに調整し、そのタイムゾーン情報を破棄します。 Postgresから値を取得すると、UTCで見られるように、常に時刻付きの日付が表示されます。一部のツールまたはミドルウェアには、データベースからの取得からプログラマーへの配信までの間にデフォルトのタイムゾーンを適用するという反機能がある場合があることに注意してください。ただし、明確にしてください。Postgresは常にタイプTIMESTAMP WITH TIME ZONE
の値を保存および取得します。 UTC、常にUTC、および offset-from-UTC
ゼロ時間-分-秒の。
これがJavaコードの例です。
LocalDate launchDateAsSeenInRome = LocalDate.of( 2021 , 1 , 23 ) ;
LocalTime launchTimeAsSeenInRome = LocalTime.of( 21 , 0 ) ;
ZoneId zoneEuropeRome = ZoneId.of( "Europe/Rome" ) ;
// Assemble those three parts to determine a moment.
ZonedDateTime launchMomentAsSeenInRome = ZonedDateTime.of( launchDateAsSeenInRome , launchTimeAsSeenInRome , zoneEuropeRome ) ;
UTCで同じ瞬間を表示するには、Instant
に変換します 。 Instant
オブジェクトは、UTCで見られるように常に瞬間を表します。
Instant launchInstant = launchMomentAsSeenInRome.toInstant() ; // Adjust from Rome time zone to UTC.
Z
上記の文字列の例の最後にあるのはUTCの標準表記であり、「ズールー」と発音されます。
残念ながら、JDBC 4.2チームは、Instant
またはZonedDateTime
種類。したがって、JDBCドライバー
そのようなオブジェクトをデータベースに対して読み取り/書き込みできる場合とできない場合があります。そうでない場合は、単に OffsetDateTime
。 3つのタイプはすべて、タイムライン上の特定のポイントである瞬間を表します。ただし、OffsetDateTime
JDBC
で必要なサポートがあります 4.2
私を逃れる理由で。
OffsetDateTime odtLaunchAsSeenInRome = launchMomentAsSeenInRome.toOffsetDateTime() ;
データベースへの書き込み。
myPreparedStatement.setObject( … , odtLaunchAsSeenInRome ) ;
データベースからの取得。
OffsetDateTime launchMoment = myResultSet.getObject( … , OffsetDateTime.class ) ;
ユーザーが希望するニューヨークのタイムゾーンに調整します。
ZoneId zoneAmericaNewYork = ZoneId.of( "America/New_York" ) ;
ZonedDateTime launchAsSeenInNewYork = launchMoment.atZoneSameInstant( zoneAmericaNewYork ) ;
上記のすべての
ちなみに、過去の出来事を追跡することも瞬間として扱われます。患者が実際に予約のために到着したのはいつですか、顧客が請求書を支払ったのはいつですか、新入社員がドキュメントに署名したのはいつですか、サーバーはいつクラッシュしましたか...これらはすべてUTCで瞬間として追跡されます。上で説明したように、通常はInstant
、ただしZonedDateTime
&OffsetDateTime
また、瞬間を表します。データベースには、TIMESTAMP WITH TIME ZONE
を使用します (WITHOUT
ではありません 。
時刻
ほとんどのビジネス指向のアプリは、特定の瞬間ではなく時刻のある日付を目指す、他のタイプの予定に焦点を合わせていると思います。
ユーザーが医療提供者とテストの結果を確認するための予約をする場合、ユーザーはその日の特定の時刻にそれを行います。その間に、政治家がタイムゾーンのルールを変更し、時計を1時間、30分、またはその他の時間の前後に移動した場合、その医療予約の日付と時刻は同じままです。実際には、元の予定のタイムラインのポイントは、政治家がタイムゾーンを変更した後に変更され、タイムラインの前/後のポイントにシフトします。
そのような予定については、しません。 UTCで表示される日付と時刻を保存します。 しない データベースの列タイプTIMESTAMP WITH TIME ZONE
を使用します 。
そのような予定については、タイムゾーンに関係なく、時刻とともに日付を保存します。タイプTIMESTAMP WITHOUT TIME ZONE
のデータベース列を使用します (WITHOUT
に注意してください WITH
ではなく )。 Javaで一致するタイプはLocalDateTime
です。 。
LocalDate medicalApptDate = LocalDate.of( 2021 , 1 , 23 ) ;
LocalTime medicalApptTime = LocalTime.of( 21 , 0 ) ;
LocalDateTime medicalApptDateTime = LocalDateTime.of( medicalApptDate , medicalApptTime ) ;
それをデータベースに書き込んでください。
myPreparedStatement.setObject( … , medicalApptDateTime ) ;
これを明確にしてください:LocalDateTime
オブジェクトはしません 瞬間を表しますが、ではありません タイムライン上の特定のポイント。 LocalDateTime
オブジェクトは、可能なの範囲を表します タイムラインの約26〜27時間に沿った瞬間(世界中のタイムゾーンの範囲)。 LocalDateTime
に本当の意味を与えるため 、目的のタイムゾーンを関連付ける必要があります。
その目的のタイムゾーンでは、2番目の列を使用してゾーン識別子を格納します。たとえば、文字列Europe/Rome
またはAmerica/New_York
。 ゾーン名のリスト
を参照してください。 。
ZoneId zoneEuropeRome = ZoneId.of( "Europe/Rome" ) ;
それをテキストとしてデータベースに書き込みます。
myPreparedStatement.setString( … , zoneEuropeRome ) ;
検索。ゾーン名をテキストとして取得し、ZoneId
をインスタンス化します オブジェクト。
LocalDateTime medicalApptDateTime = myResultSet.getObject( … , LocalDateTime.class ) ;
ZoneId medicalApptZone = ZoneId.of( myResultSet.getString( … ) ) ;
これら2つの要素を組み合わせて、ZonedDateTime
として表される瞬間を決定します。 物体。カレンダーをスケジュールする必要がある場合は、これを動的に実行します。ただし、しない 瞬間を保存します。将来、政治家がタイムゾーンを再定義する場合は、別の瞬間を計算する必要があります。
ZonedDateTime medicalApptAsSeenInCareProviderZone = ZonedDateTime.of( medicalApptDateTime , medicalApptZone ) ;
ユーザーは米国ニューヨークに旅行しています。彼らは、ニューヨークの一時的な場所にある壁の時計に従って、イタリアのミラノの医療提供者にいつ電話するかを知る必要があります。したがって、あるタイムゾーンから別のタイムゾーンに調整します。同じ瞬間、異なる実時間。
ZoneId zoneAmericaNewYork = ZoneId.of( "America/New_York" ) ;
ZonedDateTime medicalApptAsSeenInNewYork = medicalApptAsSeenInCareProviderZone.withZoneSameInstant( zoneAmericaNewYork ) ;
tzdata
希望するタイムゾーンのルールが変更される可能性がある場合は、コンピューター上のタイムゾーン定義のコピーを更新する必要があることに注意してください。
Javaには、 tzdataの独自のコピーが含まれています。 、Postgresデータベースエンジンもそうです。また、ホストオペレーティングシステムも同様です。ここに示されているこの特定のコードは、Javaのみが最新である必要があります。 Postgresを使用してタイムゾーンを調整する場合、その tzdata また、最新である必要があります。また、ログ記録などのために、ホストOSを最新の状態に保つ必要があります。ユーザーが適切に時計を監視するには、クライアントマシンのOSも最新である必要があります。
注意:世界中の政治家は、驚くべき頻度でタイムゾーンを変更する傾向を示しており、多くの場合、事前の警告はほとんどありません。
java.timeについて
java.time
フレームワークはJava8以降に組み込まれています。これらのクラスは、厄介な古いレガシー
に取って代わります。 java.util.Date
、 Calendar
、& SimpleDateFormat
。
詳細については、Oracleチュートリアルを参照してください。
。そして、StackOverflowで多くの例と説明を検索してください。仕様は
Joda-Time プロジェクト、現在メンテナンスモード 、 java.time クラス。
java.timeを交換できます データベースに直接オブジェクトを追加します。 JDBCドライバー
を使用します JDBC4.2
に準拠 またはそれ以降。文字列は必要ありません。java.sql.*
も必要ありません。 クラス。 Hibernate5およびJPA2.2はjava.timeをサポートします 。
java.timeクラスはどこで入手できますか?
- Java SE 8
、 Java SE 9
、 Java SE 10
、 Java SE 11
、およびそれ以降-実装がバンドルされた標準JavaAPIの一部。
- Java 9 いくつかのマイナーな機能と修正をもたらしました。
- Java SE 6
および
Java SE 7 - java.timeのほとんど 機能は、 ThreeTen-BackportでJava6および7にバックポートされます。 。
- Android
- 以降のバージョンのAndroid(26以降)には、 java.timeの実装がバンドルされています。 クラス。
- 以前のAndroid(<26)の場合、として知られるプロセスAPIの脱糖
java.timeのサブセットをもたらします
もともとAndroidに組み込まれていない機能。
- 脱糖によって必要なものが提供されない場合は、 ThreeTenABP
プロジェクトは
ThreeTen-Backportを採用しています (上記)Androidへ。 ThreeTenABPの使用方法…をご覧ください。 。
- 脱糖によって必要なものが提供されない場合は、 ThreeTenABP
プロジェクトは