Saya menggunakan java.util.Date
kelas Java di Scala dan ingin membandingkan Date
objek dan waktu saat ini. Saya tahu saya bisa menghitung delta dengan menggunakan getTime ():
(new java.util.Date()).getTime() - oldDate.getTime()
Namun, ini hanya membuat saya long
mewakili milidetik. Apakah ada cara yang lebih sederhana dan lebih bagus untuk mendapatkan waktu delta?
Date
,Calendar
danSimpleDateFormat
”.java.time.Period
dan / atauDuration
. Lihat jawaban Basil Bourque di bawah ini .Jawaban:
Date
Sayangnya, API JDK rusak parah. Saya sarankan menggunakan perpustakaan Joda Time .Joda Time memiliki konsep Interval waktu :
EDIT: Omong-omong, Joda memiliki dua konsep:
Interval
untuk mewakili interval waktu antara dua instance waktu (mewakili waktu antara 8 pagi dan 10 pagi), danDuration
yang mewakili panjang waktu tanpa batas waktu yang sebenarnya (misalnya, mewakili dua jam!)Jika Anda hanya peduli tentang perbandingan waktu, sebagian besar
Date
implementasi (termasuk JDK satu) mengimplementasikanComparable
antarmuka yang memungkinkan Anda untuk menggunakanComparable.compareTo()
sumber
Comparable.compareTo()
, tidakComparable.compare()
.java.time
Paket baru di Java 8 terinspirasi oleh Joda-Time tetapi bukan pengganti drop-in. Masing-masing memiliki pro dan kontra. Untungnya Anda tidak harus memilih di antara mereka. Gunakan masing-masing untuk kekuatannya selama Anda berhati-hati denganimport
pernyataan Anda . Lihat jawaban lain ini sebagai contoh java.time.Dif sederhana (tanpa lib)
Dan kemudian Anda dapat menelepon:
untuk mendapatkan perbedaan dari 2 tanggal dalam satuan menit.
TimeUnit
adalahjava.util.concurrent.TimeUnit
, enum Java standar yang beralih dari nanos ke hari.Difabel yang dapat dibaca manusia (tanpa Lib)
http://ideone.com/5dXeu6
Outputnya seperti
Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}
, dengan unit yang dipesan.Anda hanya perlu mengubah peta itu menjadi string yang mudah digunakan.
Peringatan
Cuplikan kode di atas menghitung perbedaan sederhana antara 2 instance. Ini dapat menyebabkan masalah selama sakelar penghematan siang hari, seperti dijelaskan dalam posting ini . Ini berarti jika Anda menghitung perbedaan antara tanggal tanpa waktu Anda mungkin memiliki hari / jam yang hilang.
Menurut pendapat saya, tanggal itu agak subyektif, terutama pada hari-hari tertentu. Kamu boleh:
hitung jumlah 24 jam yang telah berlalu: hari + 1 - hari = 1 hari = 24 jam
menghitung jumlah waktu yang berlalu, mengurus penghematan siang hari: hari + 1 - hari = 1 = 24 jam (tetapi menggunakan waktu tengah malam dan penghematan siang hari bisa 0 hari dan 23 jam)
hitung jumlah
day switches
, yang berarti hari + 1 1 siang - hari 11 pagi = 1 hari, bahkan jika waktu yang berlalu hanya 2 jam (atau 1 jam jika ada penghematan siang hari: p)Jawaban saya valid jika definisi tanggal berbeda pada hari sesuai dengan kasus pertama
Dengan JodaTime
Jika Anda menggunakan JodaTime, Anda bisa mendapatkan diff untuk 2 instance (milies didukung ReadableInstant) dengan:
Tetapi Anda juga bisa mendapatkan perbedaan untuk tanggal / waktu lokal:
sumber
Perhatikan bahwa ini bekerja dengan tanggal UTC, jadi perbedaannya mungkin satu hari libur jika Anda melihat tanggal lokal. Dan membuatnya bekerja dengan benar dengan tanggal lokal memerlukan pendekatan yang sama sekali berbeda karena waktu musim panas.
sumber
(endDate.getTime() - startDate.getTime())
dilemparkan keint
bukan hasil akhir, dan Anda mendapatkan integer overflow.Menggunakan kerangka java.time yang ada di dalam Java 8+:
Keluaran:
Untuk info lebih lanjut, lihat Tutorial Oracle dan standar ISO 8601 .
sumber
Period
sebagai gantiDuration
tanggal.Anda perlu mendefinisikan masalah Anda dengan lebih jelas. Anda bisa mengambil jumlah milidetik di antara dua
Date
objek dan membaginya dengan jumlah milidetik dalam 24 jam, misalnya ... tetapi:Date
selalu dalam UTCsumber
tl; dr
Konversi
java.util.Date
objek usang Anda menjadi pengganti merekajava.time.Instant
,. Kemudian hitung waktu yang telah berlalu sebagai aDuration
.Format ISO 8601:
PnYnMnDTnHnMnS
Standar masuk akal ISO 8601 mendefinisikan representasi tekstual singkat dari rentang waktu beberapa tahun, bulan, hari, jam, dll. Panggilan standar seperti rentang durasi . Formatnya adalah di
PnYnMnDTnHnMnS
manaP
berarti "Periode", yangT
memisahkan bagian tanggal dari bagian waktu, dan di antaranya adalah angka diikuti oleh huruf.Contoh:
P3Y6M4DT12H30M5S
tiga tahun, enam bulan, empat hari, dua belas jam, tiga puluh menit, dan lima detik
PT4H30M
Empat setengah jam
waktu java
The java.time kerangka dibangun ke Jawa 8 dan kemudian supplants tua merepotkan
java.util.Date
/java.util.Calendar
kelas. Kelas-kelas baru terinspirasi oleh kerangka kerja Joda-Time yang sangat sukses , dimaksudkan sebagai penggantinya, serupa dalam konsep tetapi dirancang ulang. Didefinisikan oleh JSR 310 . Diperpanjang oleh proyek ThreeTen-Extra . Lihat Tutorialnya .Saat
The
Instant
kelas merupakan saat di timeline di UTC dengan resolusi nanodetik (hingga sembilan (9) angka dari pecahan desimal).Terbaik untuk menghindari kelas warisan seperti
Date
/Calendar
. Tetapi jika Anda harus beroperasi dengan kode lama yang belum diperbarui ke java.time , konversi bolak-balik. Panggil metode konversi baru yang ditambahkan ke kelas lama. Untuk berpindah dari ajava.util.Date
keInstant
, panggilanDate::toInstant
.Rentang waktu
Kelas java.time telah membagi ide ini mewakili rentang waktu sebagai beberapa tahun, bulan, hari, jam, menit, detik menjadi dua bagian:
Period
selama bertahun-tahun, berbulan-bulan, berhari-hariDuration
selama berhari-hari, berjam-jam, menit, detikBerikut ini sebuah contoh.
Dump ke konsol.
Keduanya
Period
danDuration
menggunakan standar ISO 8601 untuk menghasilkan representasi String dari nilainya.Java 9 menambahkan metode untuk
Duration
mendapatkan bagian hari, bagian jam, bagian menit, dan bagian detik.Anda bisa mendapatkan jumlah total hari atau jam atau menit atau detik atau milidetik atau nanodetik dalam seluruh Durasi.
Di Jawa 9
Duration
kelas mendapatkan metode baru untuk mengembalikan berbagai bagian hari, jam, menit, detik, milidetik / nanodetik. Memanggilto…Part
metode:toDaysPart()
,toHoursPart()
, dan sebagainya.ChronoUnit
Jika Anda hanya peduli dengan rincian waktu yang lebih sederhana, seperti “jumlah hari yang berlalu”, gunakan
ChronoUnit
enum.Contoh lain.
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
.Proyek Joda-Time , sekarang dalam mode pemeliharaan , menyarankan migrasi ke java.time.
Untuk mempelajari lebih lanjut, lihat Tutorial Oracle . Dan cari Stack Overflow untuk banyak contoh dan penjelasan. Spesifikasi adalah JSR 310 .
Di mana mendapatkan kelas java.time?
Proyek ThreeTen-Extra memperpanjang java.time dengan kelas tambahan. Proyek ini adalah ajang pembuktian untuk kemungkinan penambahan masa depan ke java.time. Anda mungkin menemukan beberapa kelas berguna di sini seperti
Interval
,YearWeek
,YearQuarter
, dan lebih .Joda-Time
UPDATE: Proyek Joda-Time sekarang dalam mode pemeliharaan , dengan tim menyarankan migrasi ke kelas java.time . Saya membiarkan bagian ini utuh untuk sejarah.
Perpustakaan Joda-Time menggunakan ISO 8601 untuk standarnya. Its
Period
mem-parsing kelas dan menghasilkan PnYnMnDTnHnMnS ini string.Memberikan:
sumber
Period
,,Duration
danChronoUnit
, tiga kelas yang tujuannya menentukan delta antara titik waktu. Tolong tunjukkan bagian mana dari "dinding teks" saya yang tidak relevan. Dan Anda tidak benar dalam mengatakan Pertanyaannya meminta "delta antara tanggal": Pertanyaan itu meminta delta antaraDate
objek, yang merupakan momen-momen waktu-waktu, bukan "tanggal" meskipun ada nama yang tidak disukai dari kelas itu.java.util.Date
keInstant
(panggilan saja.toInstant
). Dan saya menambahkanMoment
bagian untuk menjelaskan. Anda menyebutkan sepasangDate
objek, tetapi sebenarnya Pertanyaan hanya menggunakan satuDate
objek yang ada dan kemudian menangkap momen saat ini, jadi saya melakukan hal yang sama. Terima kasih untuk umpan baliknya! Kiat: Berhenti menggunakanDate
- Kelas-kelas warisan itu benar-benar berantakan.https://www.joda.org/joda-time/faq.html#datediff
sumber
Alternatif yang sedikit lebih sederhana:
Adapun "lebih baik": baik, apa sebenarnya yang Anda butuhkan? Masalah dengan mewakili durasi waktu sebagai jumlah jam dan hari dll adalah bahwa hal itu dapat menyebabkan ketidakakuratan dan ekspektasi yang salah karena kompleksitas tanggal (misalnya hari dapat memiliki 23 atau 25 jam karena waktu musim panas).
sumber
Menggunakan pendekatan milidetik dapat menyebabkan masalah di beberapa lokal.
Mari kita ambil, misalnya, perbedaan antara dua tanggal 03/24/2007 dan 03/25/2007 harus 1 hari;
Namun, menggunakan rute milidetik, Anda akan mendapatkan 0 hari, jika Anda menjalankan ini di Inggris!
Cara yang lebih baik untuk mengimplementasikan ini adalah dengan menggunakan java.util.Calendar
sumber
Ada banyak cara Anda dapat menemukan perbedaan antara tanggal & waktu. Salah satu cara paling sederhana yang saya tahu adalah:
Pernyataan cetak hanyalah sebuah contoh - Anda dapat memformatnya, sesuai keinginan Anda.
sumber
Karena semua jawaban di sini benar tetapi menggunakan legacy java atau lib pihak ke-3 seperti joda atau serupa, saya hanya akan membuang cara lain menggunakan kelas java.time baru di Java 8 dan yang lebih baru. Lihat Tutorial Oracle .
Gunakan
LocalDate
danChronoUnit
:sumber
Mengurangkan tanggal dalam milidetik berfungsi (seperti yang dijelaskan dalam pos lain), tetapi Anda harus menggunakan HOUR_OF_DAY dan bukan HOUR saat membersihkan bagian waktu dari tanggal Anda:
sumber
Jika Anda tidak ingin menggunakan JodaTime atau yang serupa, solusi terbaik mungkin adalah ini:
Jumlah ms per hari tidak selalu sama (karena waktu musim panas dan lompatan detik), tetapi sangat dekat, dan setidaknya penyimpangan karena waktu musim panas dibatalkan lebih lama. Karenanya membagi dan kemudian membulatkan akan memberikan hasil yang benar (setidaknya selama kalender lokal yang digunakan tidak mengandung lompatan waktu yang aneh selain DST dan detik kabisat).
Perhatikan bahwa ini masih menganggap itu
date1
dandate2
diatur ke waktu yang sama dalam sehari. Untuk waktu yang berbeda dalam sehari, pertama-tama Anda harus mendefinisikan apa arti "perbedaan tanggal", seperti yang ditunjukkan oleh Jon Skeet.sumber
date1.getTime()
vsdate2.getTime()
. Jadi diffing 2016-03-03 hingga 2016-03-31 akan menghitung 27 hari sementara Anda ingin 28 hari.Math.round()
, yang tampaknya aman di kalender 'dunia nyata'. Maaf atas kebisingannya.Lihatlah Joda Time , yang merupakan API Tanggal / Waktu yang ditingkatkan untuk Java dan seharusnya bekerja dengan baik dengan Scala.
sumber
Biarkan saya menunjukkan perbedaan antara Joda Interval dan Days:
sumber
Jika Anda membutuhkan String pengembalian yang diformat seperti "2 Days 03h 42m 07s", coba ini:
sumber
std
di atas tidak ditentukan.Catatan: startDate dan endDate adalah -> java.util.Date
dan tanggal akhir
Mirip dengan hari, Anda juga bisa mendapatkan jam, menit, dan detik
sumber
Lihat contoh di sini http://www.roseindia.net/java/beginners/DateDifferent.shtml Contoh ini memberi Anda perbedaan dalam hari, jam, menit, detik, dan mili detik :).
sumber
Gunakan zona waktu GMT untuk mendapatkan instance Kalender, atur waktu menggunakan metode atur kelas Kalender. Zona waktu GMT memiliki 0 offset (tidak terlalu penting) dan bendera waktu musim panas disetel ke false.
sumber
java.util.Date
dll. Menggunakan hack untuk mengatur zona waktu ke GMT membuat kode tidak sensitif untuk efek penghematan siang hari.Kode berikut dapat memberi Anda output yang diinginkan:
sumber
sumber
sumber
Date
, jadi perbandingan ini adalah yang terbaik yang bisa dicapai mengingat keadaan.Hal terbaik untuk dilakukan adalah
Angka itu adalah jumlah milidetik dalam sehari.
Satu tanggal-tanggal lainnya memberi Anda perbedaan dalam milidetik.
Kumpulkan jawaban dalam variabel ganda .
sumber
Berikut ini adalah solusi Java 7 yang benar di O (1) tanpa ketergantungan apa pun.
sumber
Itu mungkin cara paling mudah untuk melakukannya - mungkin itu karena saya telah mengkode di Jawa (dengan perpustakaan tanggal dan waktu yang kukuh) untuk sementara waktu sekarang, tetapi kode itu terlihat "sederhana dan baik" bagi saya!
Apakah Anda senang dengan hasil yang dikembalikan dalam milidetik, atau bagian dari pertanyaan Anda yang Anda inginkan dikembalikan dalam beberapa format alternatif?
sumber
Tidak menggunakan API standar, tidak. Anda dapat melakukan sesuatu sendiri seperti ini:
Atau Anda dapat menggunakan Joda :
sumber
Hanya untuk menjawab pertanyaan awal:
Masukkan kode berikut ke dalam Function seperti Long getAge () {}
Yang paling penting di sini adalah bekerja dengan angka panjang saat mengalikan dan membagi. Dan tentu saja, offset yang diterapkan Java dalam kalkulus Tanggalnya.
:)
sumber
Karena pertanyaan ini ditandai dengan Scala,
sumber
Setelah mengarungi semua jawaban lain, untuk menjaga tipe tanggal Java 7 tetapi lebih tepat / standar dengan pendekatan Java 8 diff,
sumber
coba ini:
Anda dapat mengedit string dalam parameter metode parse ().
sumber