Bagaimana cara mendapatkan waktu mulai dan waktu akhir suatu hari?
kode seperti ini tidak akurat:
private Date getStartOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 0, 0, 0);
return calendar.getTime();
}
private Date getEndOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 23, 59, 59);
return calendar.getTime();
}
Ini tidak akurat untuk milidetik.
Jawaban:
tl; dr
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.
Lihat momen yang sama di UTC.
Jika Anda menginginkan seluruh hari dalam suatu tanggal seperti yang terlihat di UTC daripada dalam zona waktu, gunakan
OffsetDateTime
.Ini
OffsetDateTime
benda-benda yang sudah akan berada di UTC, tetapi Anda dapat menghubungitoInstant
jika Anda membutuhkan objek seperti yang selalu di UTC dengan definisi.Tip: Anda mungkin tertarik untuk menambahkan pustaka ThreeTen-Extra ke proyek Anda untuk menggunakan
Interval
kelasnya untuk mewakili pasanganInstant
objek ini. Ini menawarkan kelas metode yang berguna untuk perbandingan sepertiabuts
,overlaps
,contains
, dan banyak lagi.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 .
Joda-Time 2.3 menawarkan metode untuk tujuan ini, untuk mendapatkan momen pertama hari:
withTimeAtStartOfDay()
. Demikian pula di java.timeLocalDate::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
Instant
momen di timeline dalam UTC dengan resolusi nanodetik .Terapkan zona waktu untuk mendapatkan waktu jam dinding di beberapa wilayah.
Untuk mendapatkan momen pertama hari itu, ikuti
LocalDate
kelas danatStartOfDay
metodenya.Dengan menggunakan pendekatan Setengah Terbuka, dapatkan momen pertama di hari berikutnya.
Saat ini framework java.time tidak memiliki
Interval
kelas 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 adalahInterval
. BangunInterval
dengan melewatkan sepasangInstant
benda. Kita dapat mengekstrakInstant
dariZonedDateTime
objek kita .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
, danDuration
. AnInterval
memiliki awal dan akhir yang spesifik pada garis waktu Semesta. Ini sesuai dengan kebutuhan kita untuk mewakili "satu hari".Kami memanggil metode
withTimeAtStartOfDay
daripada menyetel waktu hari ke nol. Karena Waktu Musim Panas dan anomali lainnya, momen pertama hari itu mungkin tidak terjadi00:00:00
.Contoh kode menggunakan Joda-Time 2.3.
Jika harus, Anda dapat mengonversi ke java.util.Date.
sumber
LocalDateTime
Jawa 8
Pembaruan : Saya telah menambahkan 2 metode ini ke Kelas Utilitas Java saya di sini
Itu ada di Repositori Pusat Maven di:
Java 7 dan Sebelumnya
Dengan Apache Commons
Tanpa Apache Commons
sumber
getStartOfDay
harus:LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
Ie LocalTime, bukan LocalDateTime.getEndOfDay(Date date)
.getStartOfDay(Date date)
metode di bagian Java 8 sudah benar, yaitu LocalDateTime.MAX dan .MIN menempatkan Anda pada tanggal sedini mungkin di masa lalu dan masa depan, bukan awal dan akhir hari. Sebaliknya saya akan menyarankan .atStartOfDay () untuk memulai dan .plusDays (1) .atStartOfDay (). MinusNanos (1) untuk akhir.localDateTimeToDate(LocalDateTime startOfDay)
melempar Exception - java.lang.IllegalArgumentException: java.lang.ArithmeticException: long overflowdi getEndOfDay, Anda dapat menambahkan:
Meskipun secara matematis, Anda tidak dapat menentukan akhir hari selain dengan mengatakan "sebelum permulaan hari berikutnya".
Jadi, bukannya mengatakan,
if(date >= getStartOfDay(today) && date <= getEndOfDay(today))
, Anda harus mengatakan:if(date >= getStartOfDay(today) && date < getStartOfDay(tomorrow))
. Itu adalah definisi yang jauh lebih solid (dan Anda tidak perlu khawatir tentang presisi milidetik).sumber
java.time
Menggunakan
java.time
kerangka kerja bawaan Java 8.sumber
Local…
kelas tidak memiliki konsep zona waktu dan menyesuaikan untuk anomali. Misalnya, beberapa zona waktu memiliki perubahan DST pada tengah malam, jadi momen pertama hari itu adalah pada waktu01:00:00.0
(1 pagi) daripada00:00:00.0
nilai yang dihasilkan oleh kode ini. GunakanZonedDateTime
sebagai gantinya.Cara tambahan untuk menemukan awal hari dengan java8 java.time.ZonedDateTime alih-alih melalui
LocalDateTime
hanya memotong input ZonedDateTime ke DAYS:sumber
Untuk java 8, pernyataan satu baris berikut berfungsi. Dalam contoh ini saya menggunakan zona waktu UTC. Harap pertimbangkan untuk mengubah TimeZone yang saat ini Anda gunakan.
Jika tidak ada perbedaan waktu dengan output. Mencoba:
ZoneOffset.ofHours(0)
sumber
toInstant
adalah sintaks yang ilegal dan berlebihan secara konseptual.Java 8 atau ThreeTenABP
ZonedDateTime
LocalDateTime
Saya harap itu membantu seseorang.
sumber
Saya mencoba kode ini dan berhasil dengan baik!
sumber
ZonedDateTime
danInstant
siap membantu Anda tidak perlu menggunakanjava.sql.Timestamp
. Kelas itu adalah salah satu kelas lama yang mengerikan sekarang digantikan oleh kelas java.time . Pada JDBC 4.2, kita bisa langsung bertukar objek java.time dengan database. Campuran Anda antara kelas warisan dan kelas modern tidak masuk akal bagi saya.Solusi lain yang tidak bergantung pada kerangka kerja apa pun adalah:
Perhatikan bahwa ini mengembalikan waktu berbasis UTC
sumber
calendar.setTimeInMillis (0); memberi Anda akurasi hingga milidetik
sumber
Saya tahu ini agak terlambat, tetapi dalam kasus Java 8, jika Anda menggunakan OffsetDateTime (yang menawarkan banyak keuntungan, seperti TimeZone, Nanoseconds, dll.), Anda dapat menggunakan kode berikut:
sumber
Saya mengalami beberapa ketidaknyamanan dengan semua solusi karena saya membutuhkan jenis variabel Instan dan Zona Waktu selalu mengganggu perubahan segalanya, kemudian menggabungkan solusi. Saya melihat bahwa ini adalah pilihan yang baik.
dan kami mendapatkan hasilnya
Saya harap ini membantu Anda
sumber
Instant
objek. Tip: Anda mungkin tertarik untuk menambahkan perpustakaan ThreeTen-Extra ke proyek Anda untuk menggunakanInterval
kelasnya.Saya pikir yang paling mudah adalah seperti ini:
Milidetik ini kemudian dapat diubah menjadi Kalender, Instan, atau Tanggal Lokal sesuai kebutuhan Anda dengan Joda Time.
sumber
sumber