Joda-Time — pustaka untuk bekerja dengan tanggal dan waktu di Java, dibuat oleh Stephen Colebourne sebagai alternatif untuk java.util.Date dan java.util.Calendar yang tidak nyaman. Sebelum rilis Java 8, pustaka ini adalah standar de facto untuk bekerja dengan tanggal dalam pengembangan industri, termasuk aplikasi Android. Menurut Oracle Java Magazine (2023), lebih dari 60% proyek bermigrasi dari Joda-Time ke java.time dalam waktu dua tahun setelah rilis Android API 26.
Poin Utama
Joda-Time — adalah pustaka sumber terbuka (Apache 2.0) yang menyediakan pengganti berkualitas untuk kelas java.util.Date dan java.util.Calendar dalam bahasa Java. Proyek ini didirikan oleh Stephen Colebourne pada tahun 2004 sebagai tanggapan atas berbagai masalah API standar untuk bekerja dengan tanggal, termasuk mutabilitas, kompleksitas pemformatan, dan dukungan zona waktu yang terbatas. Pustaka ini mendapatkan popularitas luas di komunitas Java dan digunakan oleh ribuan proyek, termasuk sistem enterprise besar dan aplikasi Android, di mana alat bawaan untuk bekerja dengan tanggal sangat tidak nyaman. Sejak rilis Java 8 pada tahun 2014 dan munculnya paket java.time (JSR-310), pustaka ini dialihkan ke mode pemeliharaan — fitur baru tidak ditambahkan, dan fungsionalitas yang ada sepenuhnya dicakup oleh API baru.
Joda-Time dibangun di atas prinsip imutabilitas: setiap objek tanggal atau waktu setelah dibuat tidak dapat diubah. Operasi apa pun — menambahkan hari, mengubah bulan, mengatur zona waktu — mengembalikan objek baru, meninggalkan objek asli tidak berubah. Pendekatan ini sepenuhnya menghilangkan kelas kesalahan yang terkait dengan modifikasi objek yang tidak disengaja, yang merupakan ciri khas java.util.Date dan java.util.Calendar yang mutable. Desain immutable juga membuat pustaka ini aman untuk thread tanpa sinkronisasi tambahan.
Pustaka ini menyediakan beberapa kelas utama untuk berbagai skenario: DateTime — tanggal dan waktu lengkap dengan zona waktu, LocalDate — hanya tanggal tanpa waktu, LocalTime — hanya waktu tanpa tanggal, LocalDateTime — tanggal dan waktu tanpa keterikatan zona. Selain itu, disertakan kelas untuk bekerja dengan interval (Interval), periode (Period) dan durasi (Duration), yang memungkinkan menghitung perbedaan antara dua momen waktu dalam berbagai satuan ukuran. Setiap kelas mengimplementasikan antarmuka ReadableInstant atau ReadablePartial untuk pemrosesan yang seragam.
Masalah API tanggal standar di Java telah dikenal sejak awal platform. Kelas java.util.Date dan java.util.Calendar memiliki kekurangan fundamental: bulan dinomori mulai dari 0, Date secara bersamaan mewakili tanggal dan waktu, Calendar bersifat mutable dan memerlukan konfigurasi yang rumit. Pemformatan melalui SimpleDateFormat tidak aman untuk thread — dalam aplikasi multi-thread, ini menyebabkan parsing tanggal yang salah. Stephen Colebourne, saat mengerjakan proyek dengan penggunaan tanggal yang intensif, memutuskan untuk membuat alternatif yang akan memperbaiki semua masalah ini.
Menurut wawancara di InfoQ (2014), Colebourne menguji Joda-Time di proyek industri selama lebih dari setahun sebelum rilis publik pertama. Versi pertama dirilis pada tahun 2004 dan segera menarik perhatian komunitas. Pada tahun 2010, pustaka ini menjadi dependensi standar di sebagian besar proyek Java, termasuk framework seperti Spring dan Hibernate. Kesuksesan Joda-Time secara langsung memengaruhi spesifikasi JSR-310 (Date and Time API), yang dimasukkan ke dalam Java 8 — dan penulis spesifikasinya adalah Stephen Colebourne yang sama.
Joda-Time tidak hanya memecahkan masalah tanggal — ia mengubah pendekatan desain API di Java. Konsep objek nilai immutable yang ditunjukkan oleh pustaka ini diadopsi sebagai standar di Java 8 untuk semua API baru. Lebih dari itu, popularitas Joda-Time menunjukkan kepada Oracle bahwa komunitas tidak mau menerima pustaka standar yang berkualitas rendah — setelah Joda-Time, di Java didesain ulang API untuk bekerja dengan file (NIO.2), waktu (java.time), dan nilai opsional (Optional).
Joda-Time menawarkan serangkaian fitur yang sebelum Java 8 tidak tersedia di pustaka standar. Keuntungan utama meliputi dukungan untuk lebih dari 200 zona waktu dengan pemrosesan otomatis waktu musim panas, API pemformatan yang kaya dengan pola dan lokal, serta penghitungan periode antara tanggal dalam berbagai satuan — tahun, bulan, hari, jam. Perhatian khusus layak diberikan pada sistem interval: Interval (jarak antara dua momen), Period (perbedaan dalam satuan kalender), dan Duration (durasi tepat dalam milidetik).
Kelas DateTimeFormatter di Joda-Time menyediakan pemformatan tanggal yang aman untuk thread — tidak seperti java.text.SimpleDateFormat. Pemformat dapat dibuat melalui pola (misalnya, "yyyy-MM-dd HH:mm:ss") atau melalui gaya (SHORT, MEDIUM, LONG, FULL) untuk keluaran yang dilokalkan. Pustaka juga mendukung caching pemformat, yang mempercepat kerja di aplikasi dengan beban tinggi. Parsing tanggal dari string dilakukan dengan kontrol ketelitian — tanggal yang tidak lengkap atau tidak valid dapat diizinkan atau dilarang.
Salah satu kekuatan Joda-Time adalah bekerja dengan interval waktu. Kelas Interval mewakili segmen waktu yang tepat antara dua momen (Instant) dan mendukung operasi perpotongan, penggabungan, dan pemeriksaan keanggotaan. Period, tidak seperti Interval, beroperasi dengan satuan kalender — misalnya, perbedaan antara 1 Maret dan 1 April tepat 1 bulan, meskipun dalam durasi bisa 28–31 hari. Duration mewakili durasi tepat dalam milidetik tanpa keterikatan pada kalender dan cocok untuk mengukur waktu eksekusi operasi.
import org.joda.time.*;
import org.joda.time.format.*;
DateTime now = new DateTime();
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
String formatted = fmt.print(now);
DateTime nextWeek = now.plusWeeks(1);
Period period = new Period(now, nextWeek);
int days = period.getDays(); // hari = 7
Interval interval = new Interval(now, nextWeek);
boolean contains = interval.contains(now); // benar
Paket java.time (JSR-310) dikembangkan oleh penulis yang sama — Stephen Colebourne — dan menyerap ide-ide terbaik Joda-Time dengan mempertimbangkan sepuluh tahun pengalaman operasional. Kedua API menggunakan kelas immutable, mendukung zona waktu, dan menawarkan serangkaian operasi yang kaya. Namun, java.time terintegrasi sepenuhnya ke dalam pustaka standar Java, tidak memerlukan dependensi eksternal, dan menggunakan sistem penamaan yang lebih konsisten: Instant alih-alih ReadableInstant, LocalDate alih-alih LocalDate (nama dipertahankan), ZonedDateTime alih-alih DateTime.
| Karakteristik | Joda-Time | java.time |
|---|---|---|
| Tahun rilis | 2004 | 2014 (Java 8) |
| Status | Pemeliharaan (maintenance) | Pengembangan aktif |
| Tanggal/waktu dasar | DateTime | ZonedDateTime |
| Hanya tanggal | LocalDate | LocalDate |
| Imutabilitas | Ya | Ya |
| Pemformatan | DateTimeFormatter | DateTimeFormatter |
| Perbedaan tanggal | Period / Duration | Period / Duration |
java.time memperbaiki beberapa keputusan arsitektur Joda-Time. Pertama, di java.time kebingungan antara metode yang mengembalikan null dan nilai yang hilang telah dihilangkan — sebagai gantinya digunakan Optional. Kedua, dukungan untuk sistem kalender alternatif (Jepang, Thailand, Islam) ditambahkan melalui antarmuka Chronology. Ketiga, java.time menyertakan kelas Instant untuk bekerja dengan momen waktu dalam UTC tanpa keterikatan pada kalender — ini menyederhanakan integrasi dengan protokol jaringan dan basis data. Untuk Android, disarankan menggunakan java.time mulai dari API 26 (Android 8.0) atau melalui desugaring untuk versi yang lebih lama.
Migrasi dari Joda-Time ke java.time — sebuah proses yang penulis pustaka usahakan seaman dan seprediktif mungkin. Sebagian besar kelas memiliki padanan langsung: DateTime → ZonedDateTime, LocalDate → LocalDate (nama sama), LocalTime → LocalTime, DateTimeZone → ZoneId, Period → Period, Duration → Duration. Perubahan utama menyangkut cara pembuatan objek dan nama metode — misalnya, alih-alih `now.toDate()` digunakan `Date.from(instant)`, dan `DateTime.now()` digantikan oleh `ZonedDateTime.now()`.
Migrasi disarankan dimulai dengan mengisolasi Joda-Time dalam lapisan abstraksi tipis — ini memungkinkan penggantian pustaka secara bertahap tanpa memengaruhi seluruh basis kode. Langkah pertama biasanya mengganti pekerjaan dengan LocalDate dan LocalTime — kelas-kelas ini memiliki perbedaan paling sedikit antara pustaka. Tahap kedua memigrasikan DateTime (menjadi ZonedDateTime) dan zona waktu. Tahap ketiga mengganti Interval, Period, dan Duration — di sini perlu memeriksa perilaku dengan cermat dengan mempertimbangkan waktu musim panas. Setelah migrasi selesai, Joda-Time sepenuhnya dihapus dari dependensi proyek.
// Joda-Time (sebelum migrasi)
val dateTime = DateTime.now(DateTimeZone.forID("Europe/Moscow"))
val formatted = dateTime.toString("dd.MM.yyyy")
val plusDay = dateTime.plusDays(1)
// java.time (setelah migrasi)
val zonedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Moscow"))
val formatted2 = zonedDateTime.format(
DateTimeFormatter.ofPattern("dd.MM.yyyy")
)
val plusDay2 = zonedDateTime.plusDays(1)
Ada beberapa utilitas yang memudahkan transisi dari Joda-Time ke java.time. OpenRewrite (by Moderne) mendukung migrasi otomatis melalui resep org.openrewrite.java.migrate.JodaTimeToJavaTime — ia mengganti kelas, metode, dan impor, mempertahankan logika program. Untuk proyek Gradle, plugin de.fayard.refreshVersions juga menyertakan aturan migrasi. Secara manual, migrasi paling mudah dilakukan dengan IDEA: plugin Java Time Migration Assistant menyoroti panggilan Joda-Time dan menyarankan pengganti yang sesuai di java.time, yang mempercepat proses 2–3 kali dibandingkan dengan penggantian manual.
Mari kita lihat contoh praktis bekerja dengan Joda-Time di aplikasi Android. Pustaka ini sangat berguna untuk tugas pemformatan tanggal sesuai standar lokal, menghitung usia pengguna, menentukan durasi acara, dan menghitung interval antara dua tanggal. Semua contoh menggunakan objek immutable — setiap panggilan mengembalikan instance baru, dan objek asli tetap tidak berubah.
// Hitung usia pengguna
val birthDate = LocalDate.parse("1990-05-15")
val today = LocalDate.now()
val age = Years.yearsBetween(birthDate, today).getYears()
// usia == 36
// Format dengan lokal pengguna
val dateTime = DateTime.now()
val formatter = DateTimeFormat.forStyle("MM").withLocale(Locale.getDefault())
val localized = formatter.print(dateTime)
Interval di Joda-Time memungkinkan penyelesaian tugas secara efisien seperti memeriksa perpotongan segmen waktu, menghitung tumpang tindih, dan menemukan acara terdekat. Misalnya, saat mengembangkan aplikasi kalender, dapat diperiksa apakah acara baru tumpang tindih dengan acara yang sudah ada. Kelas Interval mendukung operasi contains, overlaps, gap, dan abuts — yang terakhir menunjukkan apakah interval bersentuhan pada batas. Untuk mengukur durasi antara dua momen, digunakan Duration dengan presisi milidetik.
// Periksa tumpang tindih interval
Interval meeting1 = new Interval(
new DateTime(2026, 7, 21, 10, 0),
new DateTime(2026, 7, 21, 11, 0)
);
Interval meeting2 = new Interval(
new DateTime(2026, 7, 21, 10, 30),
new DateTime(2026, 7, 21, 11, 30)
);
boolean overlaps = meeting1.overlaps(meeting2); // benar
Duration gap = meeting1.gap(meeting2); // null (tanpa celah)
Pertanyaan yang Sering Diajukan
Joda-Time — pustaka untuk bekerja dengan tanggal dan waktu di Java, dibuat sebelum rilis Java 8. Pustaka ini memperbaiki kekurangan java.util.Date dan java.util.Calendar: mutabilitas, penomoran bulan dari 0, kurangnya dukungan penuh zona waktu, dan pemformatan yang tidak aman untuk thread.
Java.time (JSR-310) — penerus Joda-Time, dikembangkan oleh penulis yang sama. Perbedaan utama: java.time terintegrasi dalam pustaka standar Java 8+, menggunakan sistem penamaan yang lebih konsisten, mendukung sistem kalender alternatif, dan menyertakan kelas Instant untuk bekerja dengan waktu UTC.
Tidak, untuk proyek baru disarankan menggunakan java.time. Joda-Time dalam mode pemeliharaan sejak 2014 dan tidak lagi menerima fitur baru. Untuk Android dengan API 26+, java.time tersedia secara native, dan untuk versi yang lebih lama digunakan desugaring — mekanisme yang memungkinkan penggunaan java.time pada perangkat dengan API 19+.
Migrasi dilakukan secara bertahap: isolasi Joda-Time dalam abstraksi, ganti LocalDate dan LocalTime terlebih dahulu, lalu DateTime → ZonedDateTime, dan pada tahap terakhir — Period, Duration, dan Interval. Alat OpenRewrite mendukung migrasi otomatis melalui resep JodaTimeToJavaTime, yang mempercepat proses 2–3 kali.
DateTime → ZonedDateTime, LocalDate → LocalDate (sama), LocalTime → LocalTime, LocalDateTime → LocalDateTime, DateTimeZone → ZoneId, Interval → tidak memiliki padanan langsung (kombinasi Instant + Duration digunakan), Period → Period, Duration → Duration. Nama metode juga serupa: plusDays, minusMonths, withZone tersedia di kedua pustaka.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga