Joda-Time — Java-da tarix və vaxt ilə işləmək üçün kitabxana, Stephen Colebourne tərəfindən əlverişsiz java.util.Date və java.util.Calendar-a alternativ olaraq yaradılmışdır. Java 8-in buraxılmasından əvvəl bu kitabxana, o cümlədən Android tətbiqləri də daxil olmaqla, sənaye inkişafında tarixlərlə işləmək üçün faktiki standart idi. Oracle Java Magazine (2023) məlumatlarına görə, layihələrin 60%-dən çoxu Android API 26-nın buraxılmasından sonra iki il ərzində Joda-Time-dan java.time-a miqrasiya etdi.
Əsas məqamlar
Joda-Time — Java dilində java.util.Date və java.util.Calendar siniflərinə keyfiyyətli əvəz təmin edən açıq mənbə (Apache 2.0) kitabxanasıdır. Layihə Stephen Colebourne tərəfindən 2004-cü ildə standart tarix API-lərinin çoxsaylı problemlərinə, o cümlədən mutasiya oluna bilmə, formatlaşdırmanın mürəkkəbliyi və saat qurşaqlarının məhdud dəstəyinə cavab olaraq yaradılmışdır. Kitabxana Java cəmiyyətində geniş yayılma qazanmış və minlərlə layihədə, o cümlədən iri enterprise sistemlərdə və Android tətbiqlərində istifadə edilmişdir, burada daxili tarix alətləri xüsusilə əlverişsiz idi. 2014-cü ildə Java 8-in buraxılması və java.time (JSR-310) paketinin meydana çıxmasından etibarən kitabxana dəstək rejiminə keçirilmişdir — yeni funksiyalar əlavə edilmir, mövcud funksionallıq isə yeni API ilə tam əhatə olunur.
Joda-Time dəyişməzlik prinsipi üzərində qurulmuşdur: yaradıldıqdan sonra hər bir tarix və ya vaxt obyekti dəyişdirilə bilməz. Hər bir əməliyyat — gün əlavə etmək, ayı dəyişdirmək, saat qurşağını təyin etmək — orijinalı dəyişməz qoyaraq yeni obyekt qaytarır. Bu yanaşma mutasiya oluna bilən java.util.Date və java.util.Calendar üçün xarakterik olan obyektlərin qəsdən olmayan dəyişdirilməsi ilə bağlı səhvlər sinfini tamamilə aradan qaldırır. Dəyişməz dizayn həmçinin kitabxananı əlavə sinxronizasiya olmadan thread-təhlükəsiz edir.
Kitabxana müxtəlif ssenarilər üçün bir neçə əsas sinif təqdim edir: DateTime — saat qurşağı ilə tam tarix və vaxt, LocalDate — vaxtsız yalnız tarix, LocalTime — tarixsiz yalnız vaxt, LocalDateTime — qurşağa bağlı olmayan tarix və vaxt. Bundan əlavə, intervallarla (Interval), dövrlərlə (Period) və müddətlərlə (Duration) işləmək üçün siniflər daxildir ki, bunlar müxtəlif ölçü vahidlərində iki vaxt anı arasındakı fərqi hesablamağa imkan verir. Hər bir sinif vahid emal üçün ReadableInstant və ya ReadablePartial interfeysini tətbiq edir.
Java-da standart tarix API-lərinin problemi platformanın yaranmasından bəri məlum idi. java.util.Date və java.util.Calendar siniflərinin əsas çatışmazlıqları var idi: aylar 0-dan nömrələnirdi, Date eyni anda həm tarixi, həm də vaxtı təmsil edirdi, Calendar mutasiya oluna bilən idi və mürəkkəb konfiqurasiya tələb edirdi. SimpleDateFormat vasitəsilə formatlaşdırma thread-təhlükəsiz deyildi — çoxthreadli tətbiqlərdə bu səhv tarix analizinə səbəb olurdu. Stephen Colebourne tarixlərdən intensiv istifadə edən layihələr üzərində işləyərkən bütün bu problemləri həll edəcək bir alternativ yaratmaq qərarına gəldi.
InfoQ (2014) müsahibəsinə görə, Colebourne Joda-Time-i ilk ictimai buraxılışdan əvvəl bir ildən çox sənaye layihələrində sınaqdan keçirmişdir. İlk versiya 2004-cü ildə buraxılmış və dərhal cəmiyyətin diqqətini cəlb etmişdir. 2010-cu ilə qədər kitabxana Spring və Hibernate kimi frameworklər də daxil olmaqla əksər Java layihələrində standart asılılığa çevrilmişdir. Joda-Time-in uğuru Java 8-ə daxil edilmiş JSR-310 (Date and Time API) spesifikasiyasına birbaşa təsir göstərmişdir — və spesifikasiyanın müəllifi eyni Stephen Colebourne olmuşdur.
Joda-Time sadəcə tarix problemini həll etmədi — Java-da API dizaynına yanaşmanı dəyişdirdi. Kitabxana tərəfindən nümayiş etdirilən dəyişməz dəyər obyektləri konsepsiyası Java 8-də bütün yeni API-lər üçün standart olaraq qəbul edildi. Üstəlik, Joda-Time-in populyarlığı Oracle-a göstərdi ki, cəmiyyət keyfiyyətsiz standart kitabxanalarla barışmağa hazır deyil — Joda-Time-dan sonra Java-da fayllarla (NIO.2), vaxtla (java.time) və opsional dəyərlərlə (Optional) işləmək üçün API-lər yenidən işlənmişdir.
Joda-Time Java 8-dən əvvəl standart kitabxanada mövcud olmayan imkanlar dəsti təqdim edir. Əsas üstünlüklərə 200-dən çox saat qurşağının dəstəyi yay vaxtının avtomatik emalı ilə, nümunələr və lokallarla zəngin formatlaşdırma API-si, habelə müxtəlif vahidlərdə — illər, aylar, günlər, saatlarla tarixlər arasında dövrlərin hesablanması daxildir. Xüsusi diqqət interval sistemi: Interval (iki an arasında fasilə), Period (təqvim vahidlərində fərq) və Duration (milisaniyələrdə dəqiq müddət).
Joda-Time-də DateTimeFormatter sinifi java.text.SimpleDateFormat-dən fərqli olaraq thread-təhlükəsiz tarix formatlaşdırması təmin edir. Formatlayıcılar nümunələr (məsələn, "yyyy-MM-dd HH:mm:ss") və ya lokallaşdırılmış çıxış üçün stillər (SHORT, MEDIUM, LONG, FULL) vasitəsilə yaradıla bilər. Kitabxana həmçinin yüksək yüklü tətbiqlərdə işi sürətləndirən formatlayıcı keşləməni dəstəkləyir. Sətirlərdən tarixlərin analizi ciddilik nəzarəti ilə aparılır — natamam və ya yanlış tarixlərə icazə vermək və ya qadağan etmək olar.
Joda-Time-in güclü tərəflərindən biri zaman fasilələri ilə işdir. Interval sinifi iki an (Instant) arasında dəqiq zaman kəsiyini təmsil edir və kəsişmə, birləşmə və daxil olma yoxlaması əməliyyatlarını dəstəkləyir. Period, Interval-dən fərqli olaraq, təqvim vahidləri ilə işləyir — məsələn, 1 mart və 1 aprel arasındakı fərq düz 1 aydır, baxmayaraq ki, müddət baxımından 28–31 gün ola bilər. Duration isə təqvimə bağlı olmadan milisaniyələrdə dəqiq müddəti təmsil edir və əməliyyatların yerinə yetirilmə vaxtını ölçmək üçün uyğundur.
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ünlər = 7
Interval interval = new Interval(now, nextWeek);
boolean contains = interval.contains(now); // doğru
java.time (JSR-310) paketi eyni müəllif — Stephen Colebourne tərəfindən hazırlanmış və on illik istismar təcrübəsi nəzərə alınmaqla Joda-Time-in ən yaxşı ideyalarını mənimsəmişdir. Hər iki API dəyişməz siniflərdən istifadə edir, saat qurşaqlarını dəstəkləyir və zəngin əməliyyatlar dəsti təqdim edir. Bununla belə, java.time Java-nın standart kitabxanasına tam inteqrasiya olunmuşdur, xarici asılılıqlar tələb etmir və daha ardıcıl adlandırma sistemindən istifadə edir: ReadableInstant əvəzinə Instant, LocalDate əvəzinə LocalDate (ad saxlanılıb), DateTime əvəzinə ZonedDateTime.
| Xüsusiyyət | Joda-Time | java.time |
|---|---|---|
| Buraxılış ili | 2004 | 2014 (Java 8) |
| Status | Dəstək (maintenance) | Aktiv inkişaf |
| Əsas tarix/vaxt | DateTime | ZonedDateTime |
| Yalnız tarix | LocalDate | LocalDate |
| Dəyişməzlik | Bəli | Bəli |
| Formatlaşdırma | DateTimeFormatter | DateTimeFormatter |
| Tarix fərqi | Period / Duration | Period / Duration |
java.time Joda-Time-in bir neçə arxitektura qərarlarını düzəldir. Birincisi, java.time-da null qaytaran metodlar və çatışmayan dəyərlər arasındakı qarışıqlıq aradan qaldırılmışdır — bunun əvəzinə Optional istifadə olunur. İkincisi, Chronology interfeysi vasitəsilə alternativ təqvim sistemlərinin (Yapon, Tay, İslam) dəstəyi əlavə edilmişdir. Üçüncüsü, java.time təqvimə bağlı olmadan UTC-də zaman anları ilə işləmək üçün Instant sinfini ehtiva edir — bu, şəbəkə protokolları və verilənlər bazaları ilə inteqrasiyanı asanlaşdırır. Android üçün API 26-dan (Android 8.0) başlayaraq java.time-dan istifadə etmək tövsiyə olunur və ya köhnə versiyalar üçün desugaring vasitəsilə.
Joda-Time-dan java.time-a miqrasiya — kitabxana müəlliflərinin mümkün qədər təhlükəsiz və proqnozlaşdırıla bilən etməyə çalışdıqları prosesdir. Siniflərin əksəriyyətinin birbaşa analoqları var: DateTime → ZonedDateTime, LocalDate → LocalDate (ad üst-üstə düşür), LocalTime → LocalTime, DateTimeZone → ZoneId, Period → Period, Duration → Duration. Əsas dəyişikliklər obyektlərin yaradılması üsulu və metod adları ilə bağlıdır — məsələn, `now.toDate()` əvəzinə `Date.from(instant)`, `DateTime.now()` isə `ZonedDateTime.now()` ilə əvəz olunur.
Miqrasiyaya Joda-Time-i incə abstraksiya qatında izolə etməklə başlamaq tövsiyə olunur — bu, kitabxananı mərhələlərlə, bütün kod bazasına təsir etmədən əvəz etməyə imkan verir. İlk addımda adətən LocalDate və LocalTime ilə iş əvəz olunur — bu siniflər kitabxanalar arasında ən az fərqə malikdir. İkinci mərhələdə DateTime (ZonedDateTime-ə) və saat qurşaqları miqrasiya edilir. Üçüncü mərhələdə Interval, Period və Duration əvəz olunur — burada yay vaxtı nəzərə alınmaqla davranışı diqqətlə yoxlamaq lazımdır. Miqrasiya başa çatdıqdan sonra Joda-Time layihənin asılılıqlarından tamamilə silinir.
// Joda-Time (miqrasiyadan əvvəl)
val dateTime = DateTime.now(DateTimeZone.forID("Europe/Moscow"))
val formatted = dateTime.toString("dd.MM.yyyy")
val plusDay = dateTime.plusDays(1)
// java.time (miqrasiyadan 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 keçidi asanlaşdıran bir neçə alət mövcuddur. OpenRewrite (by Moderne) org.openrewrite.java.migrate.JodaTimeToJavaTime resepti vasitəsilə avtomatik miqrasiyanı dəstəkləyir — o, proqramın məntiqini qoruyaraq sinifləri, metodları və importları əvəz edir. Gradle layihələri üçün de.fayard.refreshVersions plaqini də miqrasiya qaydalarını ehtiva edir. Əl ilə miqrasiyanı IDEA ilə aparmaq daha asandır: Java Time Migration Assistant plaqini Joda-Time çağırışlarını vurğulayır və java.time-da müvafiq əvəzləri təklif edir, bu da prosesi əl ilə dəyişdirmə ilə müqayisədə 2–3 dəfə sürətləndirir.
Joda-Time ilə Android tətbiqlərində praktiki iş nümunələrinə baxaq. Kitabxana yerli standartlara uyğun tarix formatlaşdırması, istifadəçi yaşının hesablanması, hadisələrin müddətinin təyini və iki tarix arasında intervalların hesablanması üçün xüsusilə faydalıdır. Bütün nümunələr dəyişməz obyektlərdən istifadə edir — hər çağırış yeni nüsxə qaytarır, orijinal obyekt isə dəyişməz qalır.
// İstifadəçi yaşını hesabla
val birthDate = LocalDate.parse("1990-05-15")
val today = LocalDate.now()
val age = Years.yearsBetween(birthDate, today).getYears()
// yaş == 36
// İstifadəçi lokallı ilə formatla
val dateTime = DateTime.now()
val formatter = DateTimeFormat.forStyle("MM").withLocale(Locale.getDefault())
val localized = formatter.print(dateTime)
Joda-Time-də intervallar zaman kəsiklərinin kəsişməsini yoxlamaq, üst-üstə düşmələri hesablamaq və ən yaxın hadisəni tapmaq vəzifələrini effektiv həll etməyə imkan verir. Məsələn, təqvim tətbiqi hazırlayarkən yeni hadisənin mövcud hadisələrlə kəsişib-kəsişmədiyini yoxlamaq olar. Interval sinifi contains, overlaps, gap və abuts əməliyyatlarını dəstəkləyir — sonuncu intervalların sərhədlərlə toxunub-toxunmadığını göstərir. İki an arasında müddəti ölçmək üçün milisaniyə dəqiqliyi ilə Duration istifadə olunur.
// Interval üst-üstə düşməsini yoxla
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şluq yoxdur)
Tez-tez verilən suallar
Joda-Time — Java 8-in buraxılmasından əvvəl yaradılmış, Java-da tarix və vaxt ilə işləmək üçün kitabxana. O, java.util.Date və java.util.Calendar-in çatışmazlıqlarını düzəldirdi: mutasiya oluna bilmə, ayların 0-dan nömrələnməsi, saat qurşaqlarının tam dəstəyinin olmaması və thread-təhlükəsiz olmayan formatlaşdırma.
Java.time (JSR-310) — eyni müəllif tərəfindən hazırlanmış Joda-Time-in varisidir. Əsas fərqlər: java.time Java 8+ standart kitabxanasına daxildir, daha ardıcıl adlandırma sistemindən istifadə edir, alternativ təqvim sistemlərini dəstəkləyir və UTC vaxtı ilə işləmək üçün Instant sinfini ehtiva edir.
Xeyr, yeni layihələr üçün java.time istifadə etmək tövsiyə olunur. Joda-Time 2014-cü ildən dəstək rejimindədir və artıq yeni imkanlar əldə etmir. Android API 26+ üçün java.time yerli olaraq mövcuddur, köhnə versiyalar üçün isə desugaring — API 19+ olan cihazlarda java.time istifadə etməyə imkan verən mexanizm mövcuddur.
Miqrasiya mərhələlərlə aparılır: Joda-Time-i abstraksiyalarda izolə edin, əvvəlcə LocalDate və LocalTime-i, sonra DateTime → ZonedDateTime-i, və son mərhələdə — Period, Duration və Interval-i əvəz edin. OpenRewrite aləti JodaTimeToJavaTime resepti vasitəsilə avtomatik miqrasiyanı dəstəkləyir, bu da prosesi 2–3 dəfə sürətləndirir.
DateTime → ZonedDateTime, LocalDate → LocalDate (üst-üstə düşür), LocalTime → LocalTime, LocalDateTime → LocalDateTime, DateTimeZone → ZoneId, Interval → birbaşa analoqu yoxdur (Instant + Duration kombinasiyası istifadə olunur), Period → Period, Duration → Duration. Metod adları da yaxındır: plusDays, minusMonths, withZone hər iki kitabxanada mövcuddur.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun