tl; dr
LocalDate // Represents an entire day, without time-of-day and without time zone.
.now( // Capture the current date.
ZoneId.of( "Asia/Tokyo" ) // Returns a `ZoneId` object.
) // Returns a `LocalDate` object.
.atStartOfDay( // Determines the first moment of the day as seen on that date in that time zone. Not all days start at 00:00!
ZoneId.of( "Asia/Tokyo" )
) // Returns a `ZonedDateTime` object.
一日の始まり
時間帯で見た今日の全長を取得します。
開始が包括的で、終了が排他的であるハーフオープンアプローチの使用。このアプローチは、1日の最後の2分の1を占めないコードの欠陥を解決します。
ZoneId zoneId = ZoneId.of( "Africa/Tunis" ) ;
LocalDate today = LocalDate.now( zoneId ) ;
ZonedDateTime zdtStart = today.atStartOfDay( zoneId ) ;
ZonedDateTime zdtStop = today.plusDays( 1 ).atStartOfDay( zoneId ) ;
zdtStart.toString()= 2020-01-30T00:00 + 01:00 [アフリカ/チュニス]
zdtStop.toString()= 2020-01-31T00:00 + 01:00 [アフリカ/チュニス]
UTCで同じ瞬間をご覧ください。
Instant start = zdtStart.toInstant() ;
Instant stop = zdtStop.toInstant() ;
start.toString()= 2020-01-29T23:00:00Z
stop.toString()= 2020-01-30T23:00:00Z
タイムゾーンではなくUTCで表示される日付の1日全体が必要な場合は、を使用しますOffsetDateTime
。
LocalDate today = LocalDate.now( ZoneOffset.UTC ) ;
OffsetDateTime odtStart = today.atTime( OffsetTime.MIN ) ;
OffsetDateTime odtStop = today.plusDays( 1 ).atTime( OffsetTime.MIN ) ;
odtStart.toString()= 2020-01-30T00:00 + 18:00
odtStop.toString()= 2020-01-31T00:00 + 18:00
これらのOffsetDateTime
オブジェクトはすでにUTCにありますがtoInstant
、定義により常にUTCにあるオブジェクトが必要な場合は呼び出すことができます。
Instant start = odtStart.toInstant() ;
Instant stop = odtStop.toInstant() ;
start.toString()= 2020-01-29T06:00:00Z
stop.toString()= 2020-01-30T06:00:00Z
ヒント:このオブジェクトのペアを表すためにそのクラスを使用するために、プロジェクトにThreeTen-Extraライブラリを追加することに興味があるかもしれません。これは、クラスの提供など、比較のために有用な方法を、、、そしてより多くの。Interval
Instant
abuts
overlaps
contains
Interval interval = Interval.of( start , stop ) ;
interval.toString()= 2020-01-29T06:00:00Z / 2020-01-30T06:00:00Z
半開き
mprivatによって答えが正解です。彼のポイントは、1日の終わりを取得しようとするのではなく、「翌日の開始前」と比較することです。彼のアイデアは「ハーフオープン」アプローチとして知られています。このアプローチでは、ある期間の始まりは包括的で、終わりは排他的です。
- Javaの現在の日時フレームワーク(java.util.Date/CalendarおよびJoda-Time)は、どちらもエポックからのミリ秒を使用します。しかし、Java 8では、新しいJSR 310 java.time。*クラスはナノ秒の解像度を使用します。新しいクラスに切り替えた場合、最後の瞬間のミリ秒カウントを強制することに基づいて記述したコードは正しくありません。
- 他のソースからのデータの比較は、他の解像度を採用している場合に失敗します。たとえば、Unixライブラリは通常、秒単位を使用し、Postgresなどのデータベースは日時をマイクロ秒に解決します。
- 夏時間の変更の中には真夜中に発生するものもあり、さらに混乱を招く可能性があります。
Joda-Time 2.3は、まさにこの目的のために、その日の最初の瞬間を取得する方法を提供しますwithTimeAtStartOfDay()
。同様にjava.timeで、LocalDate::atStartOfDay
。
StackOverflowで「joda half-open」を検索して、詳細な説明と例を確認してください。
この投稿を参照してください。時間間隔とその他の範囲は、Bill Schneiderによりハーフオープンにする必要があります。
従来の日時クラスを避ける
java.util.Dateクラスと.Calendarクラスは、非常に面倒です。それらを避けてください。
java.timeクラスを使用します。java.timeのフレームワークは非常に成功したの公式の後継者であるジョダタイムライブラリ。
java.time
java.timeフレームワークは、Java 8以降に組み込まれています。でJava 6&7にバックポートThreeTen-バックポートのプロジェクト、さらに中のAndroidに適応ThreeTenABPのプロジェクト。
アンは、Instant
タイムライン上の瞬間であるUTCの解像度を持つナノ秒。
Instant instant = Instant.now();
タイムゾーンを適用して、特定の地域の実時間を取得します。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
その日の最初の瞬間を取得するには、LocalDate
クラスとそのatStartOfDay
メソッドを通過します。
ZonedDateTime zdtStart = zdt.toLocalDate().atStartOfDay( zoneId );
ハーフオープンアプローチを使用して、翌日の最初の瞬間を取得します。
ZonedDateTime zdtTomorrowStart = zdtStart.plusDays( 1 );
現在、java.timeフレームワークには、Interval
以下に説明するJoda -Timeのクラスがありません。ただし、ThreeTen-Extraプロジェクトは、java.timeを追加のクラスで拡張します。このプロジェクトは、java.timeに将来追加される可能性があることを証明する場です。そのクラスの中にありますInterval
。オブジェクトのInterval
ペアを渡してを構築しInstant
ます。オブジェクトInstant
からを抽出できZonedDateTime
ます。
Interval today = Interval.of( zdtStart.toInstant() , zdtTomorrowStart.toInstant() );
java.timeについて
java.timeのフレームワークは、Java 8に組み込まれており、後にされています。これらのクラスは面倒古い取って代わるレガシーのような日付時刻クラスをjava.util.Date
、Calendar
、& SimpleDateFormat
。
詳細については、Oracleチュートリアルを参照してください。スタックオーバーフローで多くの例と説明を検索してください。仕様はJSR 310です。
ジョダタイムプロジェクトは、今でメンテナンスモードへの移行をアドバイスjava.timeのクラス。
java.timeオブジェクトをデータベースと直接交換することができます。JDBC 4.2以降に準拠したJDBCドライバーを使用します。文字列もクラスも必要ありません。Hibernate 5とJPA 2.2はjava.timeをサポートしています。java.sql.*
java.timeクラスはどこで入手できますか?
ジョーダタイム
更新:Joda -Timeプロジェクトはメンテナンスモードになり、java.timeクラスへの移行を推奨します。このセクションはそのまま残しておきます。
ジョダタイムは、さまざまな方法で時間のスパンを表現するための3つのクラスがありますInterval
、Period
とDuration
。アンはInterval
、特定の開始と宇宙のタイムライン上で終了しています。これは「1日」を表すという私たちのニーズに適合します。
withTimeAtStartOfDay
時刻をゼロに設定するのではなく、メソッドを呼び出します。夏時間およびその他の異常のため、その日の最初の瞬間はそうではない場合があります00:00:00
。
Joda-Time 2.3を使用したサンプルコード。
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( timeZone );
DateTime todayStart = now.withTimeAtStartOfDay();
DateTime tomorrowStart = now.plusDays( 1 ).withTimeAtStartOfDay();
Interval today = new Interval( todayStart, tomorrowStart );
必要な場合は、java.util.Dateに変換できます。
java.util.Date date = todayStart.toDate();