Joda-Time, Stephen Colebourne tarafından hantal java.util.Date ve java.util.Calendar'a alternatif olarak oluşturulan, Java'da tarihler ve saatlerle çalışmak için bir kütüphanedir. Java 8'in piyasaya sürülmesinden önce, bu kütüphane Android uygulamaları da dahil olmak üzere endüstriyel geliştirmede tarih işleme için fiili standarttı. Oracle Java Magazine'e (2023) göre, Android API 26'nın piyasaya sürülmesinden sonraki iki yıl içinde projelerin %60'ından fazlası Joda-Time'dan java.time'a geçti.
Önemli Noktalar
Joda-Time, Java dilinde java.util.Date ve java.util.Calendar sınıflarına kaliteli bir alternatif sunan açık kaynaklı bir kütüphanedir (Apache 2.0). Proje, Stephen Colebourne tarafından 2004 yılında standart tarih ve saat API'lerinin değişebilirlik, biçimlendirme karmaşıklığı ve sınırlı saat dilimi desteği gibi çok sayıda sorununa yanıt olarak kuruldu. Kütüphane, Java topluluğunda geniş çapta benimsendi ve büyük kurumsal sistemler ve Android uygulamaları da dahil olmak üzere binlerce projede kullanıldı. 2014'te Java 8'in piyasaya sürülmesi ve java.time paketinin (JSR-310) tanıtılmasından bu yana, kütüphane bakım moduna alındı — yeni özellikler eklenmiyor ve mevcut işlevsellik yeni API tarafından tamamen kapsanıyor.
Joda-Time, değişmezlik ilkesi üzerine inşa edilmiştir: her tarih veya saat nesnesi oluşturulduktan sonra değiştirilemez. Herhangi bir işlem — bir gün eklemek, bir ayı değiştirmek, bir saat dilimi ayarlamak — orijinali değiştirmeden yeni bir nesne döndürür. Bu yaklaşım, değişebilir java.util.Date ve java.util.Calendar'ın karakteristik özelliği olan istenmeyen nesne değişiklikleriyle ilişkili hata sınıfını tamamen ortadan kaldırır. Değişmez tasarım ayrıca kütüphaneyi ek senkronizasyon olmadan iş parçacığı güvenli hale getirir.
Kütüphane, farklı senaryolar için birkaç ana sınıf sağlar: DateTime — saat dilimiyle tam tarih ve saat, LocalDate — saat olmadan yalnızca tarih, LocalTime — tarih olmadan yalnızca saat, LocalDateTime — saat dilimi bağlantısı olmadan tarih ve saat. Ayrıca, aralıklar (Interval), dönemler (Period) ve sürelerle (Duration) çalışmak için sınıflar dahil edilmiştir ve çeşitli ölçü birimlerinde iki zaman noktası arasındaki farkı hesaplamanıza olanak tanır. Her sınıf, tek tip işlem için ReadableInstant veya ReadablePartial arabirimini uygular.
Java'daki standart tarih API'lerinin sorunu, platformun başlangıcından beri biliniyordu. java.util.Date ve java.util.Calendar sınıflarının temel kusurları vardı: aylar 0'dan başlayarak numaralandırılıyordu, Date aynı anda hem tarihi hem de saati temsil ediyordu, Calendar değişebilirdi ve karmaşık yapılandırma gerektiriyordu. SimpleDateFormat ile biçimlendirme iş parçacığı güvenli değildi — çok iş parçacıklı uygulamalarda bu, hatalı tarih ayrıştırmaya yol açıyordu. Yoğun tarih kullanımı olan projelerde çalışan Stephen Colebourne, tüm bu sorunları çözecek bir alternatif oluşturmaya karar verdi.
InfoQ (2014) üzerindeki bir röportaja göre Colebourne, ilk halka açık sürümden önce Joda-Time'ı bir yıldan fazla bir süre üretim projelerinde test etti. İlk sürüm 2004 yılında yayınlandı ve hemen topluluğun dikkatini çekti. 2010 yılına gelindiğinde, kütüphane Spring ve Hibernate gibi çerçeveler de dahil olmak üzere çoğu Java projesinde standart bir bağımlılık haline gelmişti. Joda-Time'ın başarısı, Java 8'e dahil edilen JSR-310 spesifikasyonunu (Date and Time API) doğrudan etkiledi — aynı Stephen Colebourne spesifikasyon lideri olarak.
Joda-Time yalnızca tarih sorununu çözmekle kalmadı — Java'da API tasarımına yaklaşımı değiştirdi. Kütüphane tarafından gösterilen değişmez değer nesneleri kavramı, Java 8'deki tüm yeni API'ler için standart olarak kabul edildi. Ayrıca, Joda-Time'ın popülerliği Oracle'a topluluğun düşük kaliteli standart kütüphaneleri tolere etmeye istekli olmadığını gösterdi — Joda-Time'dan sonra, Java'da dosya işleme (NIO.2), zaman (java.time) ve isteğe bağlı değerler (Optional) için API'ler yeniden tasarlandı.
Joda-Time, Java 8'den önce standart kütüphanede bulunmayan bir dizi özellik sunar. Başlıca avantajlar arasında otomatik yaz saati uygulamasıyla 200'den fazla saat dilimi desteği, desenler ve yerel ayarlarla zengin bir biçimlendirme API'si ve çeşitli birimlerde — yıllar, aylar, günler, saatler — tarihler arasındaki dönem hesaplamaları bulunur. Özellikle dikkat çeken, aralık sistemidir: Interval (iki an arasındaki süre), Period (takvim birimlerindeki fark) ve Duration (milisaniye cinsinden kesin uzunluk).
Joda-Time'daki DateTimeFormatter sınıfı, java.text.SimpleDateFormat'ın aksine iş parçacığı güvenli tarih biçimlendirmesi sağlar. Biçimlendiriciler, desenler (örn. “yyyy-MM-dd HH:mm:ss”) veya yerelleştirilmiş çıktı için stiller (SHORT, MEDIUM, LONG, FULL) aracılığıyla oluşturulabilir. Kütüphane ayrıca, yükü yüksek uygulamalarda performansı hızlandıran biçimlendirici önbelleklemesini destekler. Dizelerden tarih ayrıştırma, sıkılık kontrolüyle gerçekleştirilir — eksik veya yanlış tarihlere izin verebilir veya reddedebilirsiniz.
Joda-Timeın güçlü yönlerinden biri, zaman aralıklarıyla çalışmaktır. Interval sınıfı, iki an arasındaki kesin zaman aralığını temsil eder ve kesişim, birleşim ve içerme denetimi işlemlerini destekler. Period, Interval'ın aksine, takvim birimlerinde çalışır — örneğin, 1 Mart ile 1 Nisan arasındaki fark tam olarak 1 aydır, ancak süre olarak 28–31 gün olabilir. Duration ise takvim bağlantısı olmadan milisaniye cinsinden kesin uzunluğu temsil eder ve işlem yürütme süresini ölçmek için uygundur.
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(); // gün = 7
Interval interval = new Interval(now, nextWeek);
boolean contains = interval.contains(now); // doğru
java.time paketi (JSR-310), aynı yazar — Stephen Colebourne — tarafından geliştirilmiştir ve on yıllık işletme deneyimiyle Joda-Time'ın en iyi fikirlerini içermektedir. Her iki API de değişmez sınıflar kullanır, saat dilimlerini destekler ve zengin bir işlem seti sunar. Ancak java.time, Java standart kütüphanesine tamamen entegre edilmiştir, harici bağımlılık gerektirmez ve daha tutarlı bir adlandırma sistemi kullanır: ReadableInstant yerine Instant, LocalDate yerine LocalDate (ad korunmuştur), DateTime yerine ZonedDateTime.
| Özellik | Joda-Time | java.time |
|---|---|---|
| Yayın yılı | 2004 | 2014 (Java 8) |
| Durum | Bakım | Aktif geliştirme |
| Temel tarih/saat | DateTime | ZonedDateTime |
| Yalnızca tarih | LocalDate | LocalDate |
| Değişmezlik | Evet | Evet |
| Biçimlendirme | DateTimeFormatter | DateTimeFormatter |
| Tarih farkı | Period / Duration | Period / Duration |
java.time, Joda-Time'ın birkaç mimari kararını düzeltir. İlk olarak java.time, null döndüren yöntemlerle eksik değerler arasındaki karışıklığı ortadan kaldırır — bunun yerine Optional kullanır. İkinci olarak, Chronology arabirimi aracılığıyla alternatif takvim sistemleri (Japon, Tay, İslami) için destek eklenmiştir. Üçüncü olarak java.time, takvim bağlantısı olmadan UTC zaman anlarıyla çalışmak için Instant sınıfını içerir — bu, ağ protokolleri ve veritabanlarıyla entegrasyonu basitleştirir. Android için, API 26 (Android 8.0) ve sonrasında java.time kullanılması önerilir veya daha eski sürümler için desugaring aracılığıyla.
Joda-Time'dan java.time'a göç, kütüphane yazarlarının mümkün olduğunca güvenli ve öngörülebilir hale getirmeye çalıştığı bir süreçtir. Çoğu sınıfın doğrudan karşılıkları vardır: DateTime → ZonedDateTime, LocalDate → LocalDate (ad eşleşir), LocalTime → LocalTime, DateTimeZone → ZoneId, Period → Period, Duration → Duration. Ana değişiklikler, nesnelerin oluşturulma şekli ve yöntem adlarıyla ilgilidir — örneğin, `now.toDate()` yerine `Date.from(instant)` kullanılır ve `DateTime.now()` `ZonedDateTime.now()` ile değiştirilir.
Göçe, Joda-Timeı ince bir soyutlama katmanında izole ederek başlamanız önerilir — bu, tüm kod tabanına dokunmadan kütüphaneyi aşamalı olarak değiştirmenizi sağlar. İlk adım genellikle LocalDate ve LocalTime ile çalışmayı değiştirmektir — bu sınıflar kütüphaneler arasında en az farka sahiptir. İkinci aşamada DateTime (ZonedDateTime'a) ve saat dilimleri taşınır. Üçüncü aşamada Interval, Period ve Duration değiştirilir — burada yaz saati uygulaması davranışını dikkatlice kontrol etmeniz gerekir. Göç tamamlandıktan sonra Joda-Time, proje bağımlılıklarından tamamen kaldırılır.
// Joda-Time (göçten önce)
val dateTime = DateTime.now(DateTimeZone.forID("Europe/Moscow"))
val formatted = dateTime.toString("dd.MM.yyyy")
val plusDay = dateTime.plusDays(1)
// java.time (göçten sonra)
val zonedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Moscow"))
val formatted2 = zonedDateTime.format(
DateTimeFormatter.ofPattern("dd.MM.yyyy")
)
val plusDay2 = zonedDateTime.plusDays(1)
Joda-Time'dan java.time'a geçişi basitleştiren birkaç yardımcı program vardır. OpenRewrite (Moderne tarafından), org.openrewrite.java.migrate.JodaTimeToJavaTime tarifi aracılığıyla otomatik göçü destekler — program mantığını korurken sınıfları, yöntemleri ve importları değiştirir. Gradle projeleri için, de.fayard.refreshVersions eklentisi de göç kuralları içerir. Manuel olarak, göçü IDEA ile gerçekleştirmek en kolayıdır: Java Time Migration Assistant eklentisi Joda-Time çağrılarını vurgular ve java.time'da karşılık gelen değiştirmeleri önerir, bu da süreci manuel değiştirmeye kıyasla 2–3 kat hızlandırır.
Android uygulamalarında Joda-Time ile çalışmanın pratik örneklerine bakalım. Kütüphane, tarihleri yerel standartlara göre biçimlendirmek, kullanıcı yaşını hesaplamak, etkinlik süresini belirlemek ve iki tarih arasındaki aralıkları hesaplamak için özellikle kullanışlıdır. Tüm örnekler değişmez nesneler kullanır — her çağrı yeni bir örnek döndürürken, orijinal nesne değişmeden kalır.
// Kullanıcı yaşını hesapla
val birthDate = LocalDate.parse("1990-05-15")
val today = LocalDate.now()
val age = Years.yearsBetween(birthDate, today).getYears()
// yaş == 36
// Kullanıcı yerel ayarıyla biçimlendir
val dateTime = DateTime.now()
val formatter = DateTimeFormat.forStyle("MM").withLocale(Locale.getDefault())
val localized = formatter.print(dateTime)
Joda-Time'daki aralıklar, zaman aralığı çakışmasını kontrol etme, kesişimleri hesaplama ve en yakın etkinliği bulma gibi görevleri verimli bir şekilde çözmenizi sağlar. Örneğin, bir takvim uygulaması geliştirirken, yeni bir etkinliğin mevcut etkinliklerle çakışıp çakışmadığını kontrol edebilirsiniz. Interval sınıfı, contains, overlaps, gap ve abuts işlemlerini destekler — sonuncusu, aralıkların sınırlarında birbirine değip değmediğini gösterir. Duration, iki an arasındaki uzunluğu milisaniye hassasiyetiyle ölçmek için kullanılır.
// Aralık çakışmasını kontrol et
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); // doğru
Duration gap = meeting1.gap(meeting2); // null (boşluk yok)
Sıkça Sorulan Sorular
Joda-Time, Java 8'in piyasaya sürülmesinden önce oluşturulmuş, Java'da tarihler ve saatlerle çalışmak için bir kütüphanedir. java.util.Date ve java.util.Calendar'ın eksikliklerini düzeltti: değişebilirlik, 0'dan başlayan ay numaralandırması, tam saat dilimi desteği eksikliği ve iş parçacığı güvenli olmayan biçimlendirme.
Java.time (JSR-310), aynı yazar tarafından geliştirilen Joda-Time'ın halefidir. Temel farklılıklar: java.time, Java 8+ standart kütüphanesine yerleşik olup daha tutarlı bir adlandırma sistemi kullanır, alternatif takvim sistemlerini destekler ve UTC zamanıyla çalışmak için Instant sınıfını içerir.
Hayır, yeni projeler için java.time kullanılması önerilir. Joda-Time 2014'ten beri bakım modundadır ve artık yeni özellik almamaktadır. Android API 26+ için java.time yerel olarak kullanılabilir ve daha eski sürümler için desugaring kullanılır — API 19+ cihazlarda java.time kullanımına izin veren bir mekanizma.
Göç adım adım gerçekleştirilir: Joda-Time'ı soyutlamalarda izole edin, önce LocalDate ve LocalTime'ı değiştirin, ardından DateTime → ZonedDateTime ve son olarak Period, Duration ve Interval. OpenRewrite aracı, JodaTimeToJavaTime tarifi aracılığıyla otomatik göçü destekleyerek süreci 2–3 kat hızlandırır.
DateTime → ZonedDateTime, LocalDate → LocalDate (eşleşir), LocalTime → LocalTime, LocalDateTime → LocalDateTime, DateTimeZone → ZoneId, Interval → doğrudan karşılığı yok (Instant + Duration kombinasyonu kullanılır), Period → Period, Duration → Duration. Yöntem adları da benzerdir: plusDays, minusMonths, withZone her iki kütüphanede de mevcuttur.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun