Bermigrasi ke New Java 8 Date Time API

1. Ikhtisar

Dalam tutorial ini Anda akan belajar bagaimana memfaktor ulang kode Anda untuk memanfaatkan API Waktu Tanggal baru yang diperkenalkan di Java 8.

2. Sekilas tentang API Baru

Bekerja dengan kurma di Jawa dulu sulit. Pustaka tanggal lama yang disediakan oleh JDK hanya mencakup tiga kelas: java.util.Date, java.util.Calendar, dan java.util.Timezone .

Ini hanya cocok untuk tugas paling dasar. Untuk apa pun yang bahkan sangat rumit, pengembang harus menggunakan pustaka pihak ketiga atau menulis banyak kode khusus.

Java 8 memperkenalkan API Waktu Tanggal yang benar-benar baru ( java.util.time. * ) Yang secara longgar didasarkan pada pustaka Java populer yang disebut JodaTime. API baru ini secara dramatis menyederhanakan pemrosesan tanggal dan waktu dan memperbaiki banyak kekurangan dari perpustakaan tanggal lama.

1.1. Kejelasan API

Keuntungan pertama dari API baru ini adalah kejelasan - API tersebut sangat jelas, ringkas, dan mudah dipahami. Ini tidak memiliki banyak inkonsistensi yang ditemukan di perpustakaan lama seperti penomoran bidang (dalam bulan Kalender berbasis nol, tetapi hari dalam seminggu berbasis satu).

1.2. Fleksibilitas API

Keuntungan lainnya adalah fleksibilitas - bekerja dengan banyak representasi waktu . Pustaka tanggal lama hanya menyertakan satu kelas representasi waktu - java.util.Date , yang terlepas dari namanya, sebenarnya adalah stempel waktu. Ini hanya menyimpan jumlah milidetik yang telah berlalu sejak zaman Unix.

API baru memiliki banyak representasi waktu yang berbeda, masing-masing sesuai untuk kasus penggunaan yang berbeda:

  • Instan - mewakili suatu titik waktu (stempel waktu)
  • LocalDate - mewakili tanggal (tahun, bulan, hari)
  • LocalDateTime - sama dengan LocalDate , tetapi menyertakan waktu dengan presisi nanodetik
  • OffsetDateTime - sama seperti LocalDateTime , tetapi dengan offset zona waktu
  • LocalTime - waktu dengan presisi nanodetik dan tanpa informasi tanggal
  • ZonedDateTime - sama seperti OffsetDateTime , tetapi menyertakan ID zona waktu
  • OffsetLocalTime - sama seperti LocalTime , tetapi dengan offset zona waktu
  • MonthDay - bulan dan hari, tanpa tahun atau waktu
  • YearMonth - bulan dan tahun, tanpa hari atau waktu
  • Durasi - jumlah waktu yang direpresentasikan dalam detik, menit dan jam. Memiliki presisi nanodetik
  • Periode - jumlah waktu yang direpresentasikan dalam hari, bulan dan tahun

1.3. Kekekalan dan Keamanan Benang

Keuntungan lainnya adalah bahwa semua representasi waktu di Java 8 Date Time API tidak dapat diubah dan karenanya aman untuk thread.

Semua metode mutasi mengembalikan salinan baru alih-alih mengubah status objek asli.

Kelas lama seperti java.util.Date tidak aman untuk thread dan dapat menyebabkan bug konkurensi yang sangat halus.

1.4. Metode Rangkaian

Semua metode mutasi dapat dirangkai bersama, memungkinkan untuk mengimplementasikan transformasi kompleks dalam satu baris kode.

ZonedDateTime nextFriday = LocalDateTime.now() .plusHours(1) .with(TemporalAdjusters.next(DayOfWeek.FRIDAY)) .atZone(ZoneId.of("PST")); 

2. Contoh

Contoh di bawah ini akan menunjukkan cara melakukan tugas umum dengan API lama dan baru.

Mendapatkan waktu saat ini

// Old Date now = new Date(); // New ZonedDateTime now = ZonedDateTime.now(); 

Mewakili waktu tertentu

// Old Date birthDay = new GregorianCalendar(1990, Calendar.DECEMBER, 15).getTime(); // New LocalDate birthDay = LocalDate.of(1990, Month.DECEMBER, 15); 

Mengekstrak bidang tertentu

// Old int month = new GregorianCalendar().get(Calendar.MONTH); // New Month month = LocalDateTime.now().getMonth(); 

Menambah dan mengurangi waktu

// Old GregorianCalendar calendar = new GregorianCalendar(); calendar.add(Calendar.HOUR_OF_DAY, -5); Date fiveHoursBefore = calendar.getTime(); // New LocalDateTime fiveHoursBefore = LocalDateTime.now().minusHours(5); 

Mengubah bidang tertentu

// Old GregorianCalendar calendar = new GregorianCalendar(); calendar.set(Calendar.MONTH, Calendar.JUNE); Date inJune = calendar.getTime(); // New LocalDateTime inJune = LocalDateTime.now().withMonth(Month.JUNE.getValue()); 

Memotong

Pemotongan menyetel ulang semua bidang waktu yang lebih kecil dari bidang yang ditentukan. Pada contoh di bawah menit dan semua yang di bawah ini akan disetel ke nol

// Old Calendar now = Calendar.getInstance(); now.set(Calendar.MINUTE, 0); now.set(Calendar.SECOND, 0); now.set(Calendar.MILLISECOND, 0); Date truncated = now.getTime(); // New LocalTime truncated = LocalTime.now().truncatedTo(ChronoUnit.HOURS); 

Konversi zona waktu

// Old GregorianCalendar calendar = new GregorianCalendar(); calendar.setTimeZone(TimeZone.getTimeZone("CET")); Date centralEastern = calendar.getTime(); // New ZonedDateTime centralEastern = LocalDateTime.now().atZone(ZoneId.of("CET")); 

Mendapatkan rentang waktu antara dua titik waktu

// Old GregorianCalendar calendar = new GregorianCalendar(); Date now = new Date(); calendar.add(Calendar.HOUR, 1); Date hourLater = calendar.getTime(); long elapsed = hourLater.getTime() - now.getTime(); // New LocalDateTime now = LocalDateTime.now(); LocalDateTime hourLater = LocalDateTime.now().plusHours(1); Duration span = Duration.between(now, hourLater); 

Pemformatan dan penguraian waktu

DateTimeFormatter adalah pengganti SimpleDateFormat lama yang aman untuk thread dan menyediakan fungsionalitas tambahan.

// Old SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); Date now = new Date(); String formattedDate = dateFormat.format(now); Date parsedDate = dateFormat.parse(formattedDate); // New LocalDate now = LocalDate.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String formattedDate = now.format(formatter); LocalDate parsedDate = LocalDate.parse(formattedDate, formatter); 

Jumlah hari dalam sebulan

// Old Calendar calendar = new GregorianCalendar(1990, Calendar.FEBRUARY, 20); int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); // New int daysInMonth = YearMonth.of(1990, 2).lengthOfMonth();

3. Berinteraksi dengan Kode Legacy

Dalam banyak kasus, pengguna mungkin perlu memastikan interoperabilitas dengan pustaka pihak ketiga yang mengandalkan pustaka tanggal lama.

Di Java 8 kelas perpustakaan tanggal lama telah diperpanjang dengan metode yang mengubahnya menjadi objek yang sesuai dari API Tanggal baru.

Kelas baru menyediakan fungsi serupa.

Instant instantFromCalendar = GregorianCalendar.getInstance().toInstant(); ZonedDateTime zonedDateTimeFromCalendar = new GregorianCalendar().toZonedDateTime(); Date dateFromInstant = Date.from(Instant.now()); GregorianCalendar calendarFromZonedDateTime = GregorianCalendar.from(ZonedDateTime.now()); Instant instantFromDate = new Date().toInstant(); ZoneId zoneIdFromTimeZone = TimeZone.getTimeZone("PST").toZoneId(); 

4. Kesimpulan

Dalam artikel ini kami menjelajahi Date Time API baru yang tersedia di Java 8. Kami melihat kelebihannya, dibandingkan dengan API yang tidak digunakan lagi dan menunjukkan perbedaan menggunakan beberapa contoh.

Perhatikan bahwa kami hampir tidak menyentuh permukaan kemampuan API Waktu Tanggal baru. Pastikan untuk membaca dokumentasi resmi untuk menemukan berbagai alat yang ditawarkan oleh API baru.

Contoh kode dapat ditemukan di proyek GitHub.