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.
Awal hari
Dapatkan durasi penuh hari ini seperti yang terlihat pada zona waktu.
Menggunakan pendekatan Setengah Terbuka, di mana bagian awal bersifat inklusif sedangkan bagian akhir bersifat eksklusif . Pendekatan ini memecahkan kesalahan dalam kode Anda yang gagal memperhitungkan detik-detik terakhir hari itu.
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 [Afrika / Tunis]
zdtStop.toString () = 2020-01-31T00: 00 + 01: 00 [Afrika / Tunis]
Lihat momen yang sama di UTC.
Instant start = zdtStart.toInstant() ;
Instant stop = zdtStop.toInstant() ;
start.toString () = 2020-01-29T23: 00: 00Z
stop.toString () = 2020-01-30T23: 00: 00Z
Jika Anda menginginkan seluruh hari dalam suatu tanggal seperti yang terlihat di UTC daripada dalam zona waktu, gunakan 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
Ini OffsetDateTime benda-benda yang sudah akan berada di UTC, tetapi Anda dapat menghubungi toInstantjika Anda membutuhkan objek seperti yang selalu di UTC dengan definisi.
Instant start = odtStart.toInstant() ;
Instant stop = odtStop.toInstant() ;
start.toString () = 2020-01-29T06: 00: 00Z
stop.toString () = 2020-01-30T06: 00: 00Z
Tip: Anda mungkin tertarik untuk menambahkan pustaka ThreeTen-Extra ke proyek Anda untuk menggunakan Intervalkelasnya untuk mewakili pasangan Instantobjek ini. Ini menawarkan kelas metode yang berguna untuk perbandingan seperti abuts, overlaps, contains, dan banyak lagi.
Interval interval = Interval.of( start , stop ) ;
interval.toString () = 2020-01-29T06: 00: 00Z / 2020-01-30T06: 00: 00Z
Setengah Terbuka
The jawaban dengan mprivat benar. Maksudnya adalah untuk tidak mencoba mendapatkan akhir hari, tetapi membandingkan dengan "sebelum memulai hari berikutnya". Idenya dikenal sebagai pendekatan "Setengah Terbuka" di mana suatu rentang waktu memiliki awal yang inklusif sedangkan akhir bersifat eksklusif .
- Kerangka kerja tanggal-waktu Java (java.util.Date/Calendar dan Joda-Time ) keduanya menggunakan milidetik dari epoch . Namun di Java 8, kelas java.time. * JSR 310 yang baru menggunakan resolusi nanodetik. Kode apa pun yang Anda tulis berdasarkan pemaksaan hitungan milidetik saat terakhir hari akan salah jika dialihkan ke kelas baru.
- Membandingkan data dari sumber lain menjadi salah jika mereka menggunakan resolusi lain. Misalnya, pustaka Unix biasanya menggunakan seluruh detik, dan database seperti Postgres menyelesaikan tanggal-waktu menjadi mikrodetik.
- Beberapa perubahan Waktu Musim Panas terjadi selama tengah malam yang selanjutnya dapat membingungkan banyak hal.

Joda-Time 2.3 menawarkan metode untuk tujuan ini, untuk mendapatkan momen pertama hari: withTimeAtStartOfDay(). Demikian pula di java.time LocalDate::atStartOfDay,.
Telusuri StackOverflow untuk "joda setengah terbuka" untuk melihat lebih banyak diskusi dan contoh.
Lihat posting ini, Interval waktu dan rentang lainnya harus setengah terbuka , oleh Bill Schneider.
Hindari kelas tanggal-waktu lama
Kelas java.util.Date dan .Calendar terkenal merepotkan. Hindari mereka.
Gunakan kelas java.time . The java.time kerangka adalah penerus resmi yang sangat sukses Joda-Time perpustakaan.
java.time
Framework java.time dibangun di Java 8 dan yang lebih baru. Porting kembali ke Java 6 & 7 dalam proyek ThreeTen-Backport , selanjutnya diadaptasi ke Android dalam proyek ThreeTenABP .
Sebuah Instantmomen di timeline dalam UTC dengan resolusi nanodetik .
Instant instant = Instant.now();
Terapkan zona waktu untuk mendapatkan waktu jam dinding di beberapa wilayah.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Untuk mendapatkan momen pertama hari itu, ikuti LocalDatekelas dan atStartOfDaymetodenya.
ZonedDateTime zdtStart = zdt.toLocalDate().atStartOfDay( zoneId );
Dengan menggunakan pendekatan Setengah Terbuka, dapatkan momen pertama di hari berikutnya.
ZonedDateTime zdtTomorrowStart = zdtStart.plusDays( 1 );

Saat ini framework java.time tidak memiliki Intervalkelas seperti yang dijelaskan di bawah ini untuk Joda-Time. Namun, proyek ThreeTen-Extra memperluas java.time dengan kelas tambahan. Proyek ini adalah tempat pembuktian untuk kemungkinan penambahan java.time di masa mendatang. Di antara kelasnya adalah Interval. Bangun Intervaldengan melewatkan sepasang Instantbenda. Kita dapat mengekstrak Instantdari ZonedDateTimeobjek kita .
Interval today = Interval.of( zdtStart.toInstant() , zdtTomorrowStart.toInstant() );
Tentang java.time
The java.time kerangka dibangun ke Jawa 8 dan kemudian. Kelas-kelas ini menggantikan tua merepotkan warisan kelas tanggal-waktu seperti java.util.Date, Calendar, & SimpleDateFormat.
Untuk mempelajari lebih lanjut, lihat Tutorial Oracle . Dan cari Stack Overflow untuk banyak contoh dan penjelasan. Spesifikasinya adalah JSR 310 .
Proyek Joda-Time , sekarang dalam mode pemeliharaan , menyarankan migrasi ke kelas java.time .
Anda dapat bertukar objek java.time langsung dengan database Anda. Gunakan driver JDBC yang sesuai dengan JDBC 4.2 atau yang lebih baru. Tidak perlu string, tidak perlu java.sql.*kelas. Hibernate 5 & JPA 2.2 mendukung java.time .
Di mana mendapatkan kelas java.time?
Waktu Joda
UPDATE: Proyek Joda-Time sekarang dalam mode pemeliharaan, dan menyarankan migrasi ke kelas java.time . Saya meninggalkan bagian ini utuh untuk sejarah.
Joda-Time memiliki tiga kelas untuk mewakili rentang waktu dalam berbagai cara: Interval, Period, dan Duration. An Intervalmemiliki awal dan akhir yang spesifik pada garis waktu Semesta. Ini sesuai dengan kebutuhan kita untuk mewakili "satu hari".
Kami memanggil metode withTimeAtStartOfDaydaripada menyetel waktu hari ke nol. Karena Waktu Musim Panas dan anomali lainnya, momen pertama hari itu mungkin tidak terjadi 00:00:00.
Contoh kode menggunakan 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 );
Jika harus, Anda dapat mengonversi ke java.util.Date.
java.util.Date date = todayStart.toDate();