tl; dr
Instant
dan LocalDateTime
dua binatang yang sama sekali berbeda: Yang satu mewakili momen, yang lain tidak.
Instant
mewakili momen, titik tertentu dalam timeline.
LocalDateTime
mewakili tanggal dan waktu. Tetapi tidak memiliki zona waktu atau offset-dari-UTC, kelas ini tidak dapat mewakili momen . Ini mewakili momen potensial sepanjang kisaran sekitar 26 hingga 27 jam, rentang semua zona waktu di seluruh dunia.
Anggapan yang Salah
LocalDateTime
lebih merupakan representasi tanggal / jam termasuk zona waktu untuk manusia.
Pernyataan Anda salah: A tidakLocalDateTime
memiliki zona waktu . Tidak memiliki zona waktu adalah inti dari kelas itu.
Mengutip dokumen kelas itu:
Kelas ini tidak menyimpan atau mewakili zona waktu. Sebaliknya, ini adalah deskripsi tanggal, seperti yang digunakan untuk ulang tahun, dikombinasikan dengan waktu setempat seperti yang terlihat pada jam dinding. Itu tidak dapat mewakili instan pada garis waktu tanpa informasi tambahan seperti offset atau zona waktu.
Jadi Local…
berarti "tidak dikategorikan, tidak diimbangi".
Instant
An Instant
adalah momen pada timeline di UTC , hitungan nanodetik sejak zaman pertama UTC 1970 (pada dasarnya, lihat dokumen kelas untuk detail seluk-beluk). Karena sebagian besar logika bisnis, penyimpanan data, dan pertukaran data Anda harus dalam UTC, ini adalah kelas praktis yang sering digunakan.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
OffsetDateTime
Kelas OffsetDateTime
kelas mewakili momen sebagai tanggal dan waktu dengan konteks sejumlah jam-menit-detik di depan, atau di belakang, UTC. Jumlah offset, jumlah jam-menit-detik, diwakili oleh ZoneOffset
kelas.
Jika jumlah jam-menit-detik adalah nol, suatu OffsetDateTime
mewakili momen di UTC sama dengan Instant
.
ZoneOffset
The ZoneOffset
kelas merupakan offset-dari-UTC , sejumlah jam-menit-detik menjelang UTC atau di belakang UTC.
A ZoneOffset
hanyalah sejumlah jam-menit-detik, tidak lebih. Zona jauh lebih, memiliki nama dan riwayat perubahan untuk diimbangi. Jadi menggunakan zona selalu lebih baik daripada menggunakan offset belaka.
ZoneId
Sebuah zona waktu diwakili oleh ZoneId
kelas.
Misalnya, hari baru tiba di Paris daripada di Montréal , misalnya. Jadi kita perlu menggerakkan jarum jam untuk lebih merefleksikan siang (ketika Matahari langsung di atas kepala) untuk wilayah tertentu. Semakin jauh ke timur / barat dari garis UTC di Eropa barat / Afrika semakin besar offset.
Zona waktu adalah seperangkat aturan untuk menangani penyesuaian dan anomali seperti yang dilakukan oleh komunitas atau wilayah setempat. Anomali yang paling umum adalah kegilaan yang terlalu populer yang dikenal sebagai Daylight Saving Time (DST) .
Zona waktu memiliki sejarah aturan masa lalu, aturan saat ini, dan aturan dikonfirmasi untuk waktu dekat.
Aturan-aturan ini berubah lebih sering daripada yang Anda harapkan. Pastikan untuk menjaga aturan perpustakaan tanggal-waktu Anda, biasanya salinan database 'tz' , terbaru. Tetap mutakhir lebih mudah dari sebelumnya di Java 8 dengan Oracle merilis Timezone Updater Tool .
Tentukan nama zona waktu yang tepat dalam format Continent/Region
, seperti America/Montreal
, Africa/Casablanca
, atau Pacific/Auckland
. Jangan pernah menggunakan singkatan 2-4 huruf seperti EST
atau IST
karena mereka bukan zona waktu yang sebenarnya, tidak terstandarisasi, dan bahkan tidak unik (!).
Zona Waktu = Offset + Aturan Penyesuaian
ZoneId z = ZoneId.of( “Africa/Tunis” ) ;
ZonedDateTime
Pikirkan secara ZonedDateTime
konseptual sebagai Instant
dengan tugas ZoneId
.
ZonedDateTime = (Instan + ZoneId)
Untuk menangkap momen saat ini seperti yang terlihat pada waktu jam dinding yang digunakan oleh orang-orang di wilayah tertentu (zona waktu):
ZonedDateTime zdt = ZonedDateTime.now( z ) ; // Pass a `ZoneId` object such as `ZoneId.of( "Europe/Paris" )`.
Hampir semua backend Anda, database, logika bisnis, kegigihan data, pertukaran data semua harus dalam UTC. Tetapi untuk presentasi kepada pengguna, Anda perlu menyesuaikan ke dalam zona waktu yang diharapkan oleh pengguna. Ini adalah tujuan dari ZonedDateTime
kelas dan kelas formatter yang digunakan untuk menghasilkan representasi String dari nilai-nilai tanggal-waktu tersebut.
ZonedDateTime zdt = instant.atZone( z ) ;
String output = zdt.toString() ; // Standard ISO 8601 format.
Anda dapat menghasilkan teks dalam format lokal menggunakan DateTimeFormatter
.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ;
String outputFormatted = zdt.format( f ) ;
mardi 30 avril 2019 à 23 h 22 min 55 s heure de l'Inde
LocalDate
, LocalTime
,LocalDateTime
"Lokal" kelas waktu tanggal, LocalDateTime
, LocalDate
, LocalTime
, adalah jenis yang berbeda dari makhluk. Tidak terikat dengan satu lokalitas atau zona waktu. Mereka tidak terikat dengan timeline. Mereka tidak memiliki arti yang nyata sampai Anda menerapkannya ke suatu daerah untuk menemukan titik pada timeline.
Kata "Lokal" dalam nama-nama kelas ini mungkin kontra-intuitif bagi yang belum tahu. Kata itu berarti setiap lokalitas, atau setiap lokalitas, tetapi bukan lokalitas tertentu.
Jadi untuk aplikasi bisnis, tipe "Lokal" tidak sering digunakan karena hanya mewakili gagasan umum tentang kemungkinan tanggal atau waktu, bukan momen spesifik di timeline. Aplikasi bisnis cenderung peduli kapan tepatnya faktur tiba, produk dikirim untuk transportasi, karyawan dipekerjakan, atau taksi meninggalkan garasi. Jadi pengembang aplikasi bisnis menggunakan Instant
dan ZonedDateTime
kelas yang paling umum.
Jadi kapan kita akan menggunakan LocalDateTime
? Dalam tiga situasi: di mana kami ingin menerapkan tanggal dan waktu tertentu di beberapa lokasi, di mana kami memesan janji temu, atau di mana kami memiliki zona waktu yang dimaksudkan namun belum ditentukan. Perhatikan bahwa tidak satu pun dari ketiga kasus ini adalah satu titik spesifik tertentu pada timeline, tidak ada yang merupakan momen.
Suatu saat, beberapa saat
Terkadang kami ingin mewakili waktu tertentu pada hari tertentu, tetapi ingin menerapkannya di beberapa tempat di zona waktu.
Misalnya, "Natal dimulai pada tengah malam pada tanggal 25 Desember 2015" adalah a LocalDateTime
. Midnight menyerang pada saat-saat berbeda di Paris daripada di Montréal, dan berbeda lagi di Seattle dan Auckland .
LocalDate ld = LocalDate.of( 2018 , Month.DECEMBER , 25 ) ;
LocalTime lt = LocalTime.MIN ; // 00:00:00
LocalTime ldt = LocalDateTime.of( ld , lt ) ; // Xmas morning anywhere.
Contoh lain, "Perusahaan Acme memiliki kebijakan bahwa jam makan siang dimulai pukul 12:30 malam di setiap pabriknya di seluruh dunia" adalah a LocalTime
. Untuk memiliki makna yang sebenarnya, Anda perlu menerapkannya pada timeline untuk mengetahui momen 12:30 di pabrik Stuttgart atau 12:30 di pabrik Rabat atau 12:30 di pabrik Sydney .
Janji pemesanan
Situasi lain yang digunakan LocalDateTime
adalah untuk pemesanan acara mendatang (mis: janji dokter gigi). Penunjukan ini mungkin cukup jauh di masa depan sehingga Anda berisiko politisi mendefinisikan ulang zona waktu. Politisi sering memberi sedikit peringatan, atau bahkan tidak ada peringatan sama sekali. Jika Anda bermaksud "15:00 23 Januari mendatang" terlepas dari bagaimana politisi dapat bermain dengan jam, maka Anda tidak dapat merekam sesaat - yang akan melihat 15:00 berubah menjadi 14:00 atau 16:00 jika wilayah itu mengadopsi atau menjatuhkan Daylight Saving Time, sebagai contoh.
Untuk janji temu, simpan a LocalDateTime
dan a ZoneId
, disimpan secara terpisah. Kemudian, ketika membuat jadwal, sambil menentukan waktu dengan menelepon LocalDateTime::atZone( ZoneId )
untuk menghasilkan ZonedDateTime
objek.
ZonedDateTime zdt = ldt.atZone( z ) ; // Given a date, a time-of-day, and a time zone, determine a moment, a point on the timeline.
Jika perlu, Anda dapat menyesuaikan ke UTC. Ekstrak Instant
dari ZonedDateTime
.
Instant instant = zdt.toInstant() ; // Adjust from some zone to UTC. Same moment, same point on the timeline, different wall-clock time.
Zona tidak dikenal
Beberapa orang mungkin menggunakan LocalDateTime
dalam situasi di mana zona waktu atau offset tidak diketahui.
Saya menganggap kasus ini tidak pantas dan tidak bijaksana. Jika zona atau offset dimaksudkan tetapi tidak ditentukan, Anda memiliki data yang buruk. Itu seperti menyimpan harga suatu produk tanpa mengetahui mata uang yang dituju. Bukan ide yang bagus.
Semua tipe waktu tanggal
Untuk kelengkapan, berikut adalah tabel dari semua tipe tanggal yang mungkin, baik yang modern maupun yang lama di Jawa, serta yang ditentukan oleh standar SQL. Ini mungkin membantu menempatkan Instant
& LocalDateTime
kelas dalam konteks yang lebih besar.
Perhatikan pilihan aneh yang dibuat oleh tim Java dalam merancang JDBC 4.2. Mereka memilih untuk mendukung semua waktu java.time ... kecuali untuk dua kelas yang paling sering digunakan: Instant
& ZonedDateTime
.
Tapi tidak perlu khawatir. Kita dapat dengan mudah mengkonversi bolak-balik.
Konversi Instant
.
// Storing
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;
// Retrieving
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;
Konversi ZonedDateTime
.
// Storing
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject( … , odt ) ;
// Retrieving
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZone( z ) ;
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 kelas java.time .
Untuk mempelajari lebih lanjut, lihat Tutorial Oracle . Dan cari Stack Overflow untuk banyak contoh dan penjelasan. Spesifikasi adalah JSR 310 .
Anda dapat bertukar objek java.time secara langsung dengan database Anda. Gunakan driver JDBC yang sesuai dengan JDBC 4.2 atau yang lebih baru. Tidak perlu untuk string, tidak perlu untuk java.sql.*
kelas.
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 .