Joda-Time: що це, бібліотека дат та заміна на Java 8

Автор: IT Sectr Опубліковано: 2026-07-14 Час читання: 10 хв

Joda-Time — це бібліотека для роботи з датами та часом в Java, створена Стівеном Коулборном як альтернатива незручним java.util.Date та java.util.Calendar. До виходу Java 8 ця бібліотека була де-факто стандартом для роботи з датами в промисловій розробці, включаючи Android-додатки. За даними Oracle Java Magazine (2023), понад 60% проектів мігрували з Joda-Time на java.time протягом двох років після виходу Android API 26.

Головне

  • Joda-Time — бібліотека для роботи з датами та часом, попередник java.time в Java 8
  • Immutable-класи — DateTime, LocalDate, LocalTime, LocalDateTime забезпечують потокобезпеку
  • Timezone-підтримка — вбудована база часових поясів з автоматичними оновленнями
  • Міграція — java.time (JSR-310) повністю замінює Joda-Time, автори бібліотеки рекомендують перехід
  • Android — Joda-Time працює від API 1, але для Android 8+ (API 26) краще використовувати java.time

Що таке Joda-Time?

Joda-Time — це бібліотека з відкритим кодом (Apache 2.0), яка надає якісну заміну для класів java.util.Date та java.util.Calendar у мові Java. Проект був заснований Стівеном Коулборном у 2004 році як відповідь на нумерозні проблеми стандартних API роботи з датами, включаючи мутабельність, складність форматування та обмежену підтримку часових поясів. Бібліотека отримала широке поширення в Java-спільноті та використовувалася тисячами проектів, включаючи великі enterprise-системи та Android-додатки. З моменту виходу Java 8 у 2014 році та появи пакету java.time (JSR-310) бібліотека переведена в режим підтримки — нові функції не додаються, а існуючий функціонал повністю покривається новим API.

Архітектура бібліотеки

Joda-Time побудована на принципі іммутабельності: кожен об’єкт дати або часу після створення не може бути змінений. Будь-яка операція — додавання дня, зміна місяця, встановлення часового поясу — повертає новий об’єкт, залишаючи вихідний без змін. Такий підхід повністю усунає клас помилок, пов’язаних з ненавмисною модифікацією об’єктів, які були характерні для мутабельних java.util.Date та java.util.Calendar. Immutable-дизайн також робить бібліотеку потокобезпечною без додаткової синхронізації.

Базові класи Joda-Time

Бібліотека надає кілька основних класів для різних сценаріїв: DateTime — повна дата та час з часовим поясом, LocalDate — тільки дата без часу, LocalTime — тільки час без дати, LocalDateTime — дата та час без прив’язки до поясу. Крім того, включено класи для роботи з інтервалами (Interval), періодами (Period) та тривалістю (Duration), які дозволяють обчислювати різницю між двома моментами часу в різних одиницях виміру. Кожен клас реалізує інтерфейс ReadableInstant або ReadablePartial для єдинообразного опрацювання.

Історія появи Joda-Time

Проблема стандартних API дат в Java була відома з самого появи платформи. Класи java.util.Date та java.util.Calendar мали фундаментальні недоліки: місяці нумерувалися з 0, Date одночасно представляв і дату, і час, Calendar був мутабельним та вимагав складного налаштування. Форматування через SimpleDateFormat не було потокобезпечним — в багатопотокових додатках це призводило до некоректного парсингу дат. Стівен Коулборн, працюючи над проектами з інтенсивним використанням дат, вирішив створити альтернативу, яка виправила б усі ці проблеми.

За даними інтерв’ю на InfoQ (2014), Коулборн тестував Joda-Time в промислових проектах більше року до першого публічного релізу. Перша версія вийшла у 2004 році і одразу привернула увагу спільноти. До 2010 року бібліотека стала стандартною залежністю в більшості Java-проектів, включаючи такі фреймворки, як Spring та Hibernate. Успіх Joda-Time прямо повплинав на специфікацію JSR-310 (Date and Time API), яка була включена в Java 8 — причому автором специфікації став той самий Стівен Коулборн.

Вплив на Java-екосистему

Joda-Time не просто вирішила проблему дат — вона змінила підхід до проектування API в Java. Концепція іммутабельних value-об’єктів, продемонстрована бібліотекою, була прийнята як стандарт в Java 8 для всіх нових API. Більше того, популярність Joda-Time показала Oracle, що спільнота не готова миритися з неякісними стандартними бібліотеками — після Joda-Time в Java були перероблені API для роботи з файлами (NIO.2), часом (java.time) та опціональними значеннями (Optional).

Ключові можливості бібліотеки Joda-Time

Joda-Time надає набір можливостей, який до Java 8 був недоступний в стандартній бібліотеці. Основні переваги включають підтримку 200+ часових поясів з автоматичною обробкою літнього часу, багатий API форматування з патернами та локалями, а також обчислення періодів між датами в різних одиницях — роках, місяцях, днях, годинах. Окремої уваги заслужує система інтервалів: Interval (проміжок між двома моментами), Period (різниця в календарних одиницях) та Duration (точна тривалість в мілісекундах).

Форматування та парсинг

Клас DateTimeFormatter в Joda-Time надає потокобезпечне форматування дат — на відміну від java.text.SimpleDateFormat. Форматери можна створювати через патерни (наприклад, «yyyy-MM-dd HH:mm:ss») або через стилі (SHORT, MEDIUM, LONG, FULL) для локалізованого виведення. Бібліотека також підтримує кешування форматерів, що прискорює роботу в високонавантажених додатках. Парсинг дат з рядків виконується з контролем суворості — можна дозволити або заборонити неповні або некоректні дати.

Інтервали та обчислення

Одна з сильних сторін Joda-Time — робота з часовими проміжками. Клас Interval представляє точний часовий відрізок між двома моментами (моментами) та підтримує операції перетину, об’єднання та перевірки входження. Period, на відміну від Interval, оперує календарними одиницями — наприклад, різниця між 1 березня та 1 квітня становить рівно 1 місяць, хоча за тривалістю це може бути 28–31 день. Duration ж представляє точну тривалість в мілісекундах без прив’язки до календаря та підходить для вимірювання часу виконання операцій.

java
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(); // дні = 7

Interval interval = new Interval(now, nextWeek);
boolean contains = interval.contains(now); // true

Порівняння Joda-Time та java.time

Пакет java.time (JSR-310) був розроблений тим же автором — Стівеном Коулборном — та вбрав в себе найкращі ідеї Joda-Time з урахуванням десяти років експлуатаційного досвіду. Обидва API використовують immutable-класи, підтримують часові пояси та надають багатий набір операцій. Однак java.time повністю інтегрований в стандартну бібліотеку Java, не вимагає зовнішніх залежностей та використовує більш послідовну систему назв: Instant замість ReadableInstant, LocalDate замість LocalDate (назва збережена), ZonedDateTime замість DateTime.

ХарактеристикаJoda-Timejava.time
Рік виходу20042014 (Java 8)
СтатусПідтримка (maintenance)Активна розробка
Базова дата/часDateTimeZonedDateTime
Тільки датаLocalDateLocalDate
НезмінністьТакТак
ФорматуванняDateTimeFormatterDateTimeFormatter
Різниця датPeriod / DurationPeriod / Duration

Ключові відмінності

java.time виправляє кілька архітектурних рішень Joda-Time. По-перше, в java.time усунена плутанина між методами, що повертають null та відсутніми значеннями — замість цього використовуються Optional. По-друге, додана підтримка альтернативних календарних систем (японська, тайська, ісламська) через інтерфейс Chronology. По-третє, java.time включає клас Instant для роботи з моментами часу в UTC без прив’язки до календаря — це спрощує інтеграцію з мережевими протоколами та базами даних. Для Android рекомендується використовувати java.time починаючи з API 26 (Android 8.0) або через desugaring для старіших версій.

Міграція з Joda-Time на java.time

Міграція з Joda-Time на java.time — процес, який автори бібліотеки старалися зробити максимально безпечним та предбачуваним. Більшість класів мають прямі аналоги: DateTime → ZonedDateTime, LocalDate → LocalDate (назва збігається), LocalTime → LocalTime, DateTimeZone → ZoneId, Period → Period, Duration → Duration. Основні зміни стосуються способу створення об’єктів та назв методів — наприклад, замість `now.toDate()` використовується `Date.from(instant)`, а `DateTime.now()` замінюється на `ZonedDateTime.now()`.

Покрокова стратегія міграції

Начати міграцію рекомендується з ізоляції Joda-Time в тонкому шарі абстракції — це дозволить замінювати бібліотеку поэтапно, не затрогуючи всю кодову базу. Першим кроком зазвичай замінюють роботу з LocalDate та LocalTime — ці класи мають найменшу кількість відмінностей між бібліотеками. Другим етапом мігрують DateTime (на ZonedDateTime) та часові пояси. На третьому етапі замінюють Interval, Period та Duration — тут потрібно уважно перевірити поведінку з урахуванням літнього часу. Після завершення міграції Joda-Time повністю видаляється з залежностей проекту.

kotlin
// Joda-Time (до міграції)
val dateTime = DateTime.now(DateTimeZone.forID("Europe/Moscow"))
val formatted = dateTime.toString("dd.MM.yyyy")
val plusDay = dateTime.plusDays(1)

// java.time (після міграції)
val zonedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Moscow"))
val formatted2 = zonedDateTime.format(
    DateTimeFormatter.ofPattern("dd.MM.yyyy")
)
val plusDay2 = zonedDateTime.plusDays(1)

Інструменти для міграції

Існує кілька утиліт, що полегшують перехід з Joda-Time на java.time. OpenRewrite (by Moderne) підтримує автоматичну міграцію через рецепт org.openrewrite.java.migrate.JodaTimeToJavaTime — він замінює класи, методи та імпорти, зберігаючи логіку програми. Для Gradle-проектів плагін de.fayard.refreshVersions також містить правила міграції. Вручну міграцію найпростіше проводити з IDEA: плагін Java Time Migration Assistant підсвічує виклики Joda-Time та пропонує відповідні заміни на java.time, що прискорює процес в 2–3 рази порівняно з ручною заміною.

Приклади коду на Joda-Time

Розглянемо практичні приклади роботи з Joda-Time в Android-додатках. Бібліотека особливо корисна для задач форматування дат під локальні стандарти, обчислення віку користувача, визначення тривалості подій та розрахунку інтервалів між двома датами. Усі приклади використовують immutable-об’єкти — кожен виклик повертає новий екземпляр, а вихідний об’єкт залишається незмінним.

kotlin
// Обчислити вік користувача
val birthDate = LocalDate.parse("1990-05-15")
val today = LocalDate.now()
val age = Years.yearsBetween(birthDate, today).getYears()
// вік == 36

// Форматувати з локаллю користувача
val dateTime = DateTime.now()
val formatter = DateTimeFormat.forStyle("MM").withLocale(Locale.getDefault())
val localized = formatter.print(dateTime)

Робота з інтервалами

Інтервали в Joda-Time дозволяють ефективно вирішувати завдання перевірки перетину часових відрізків, розрахунку накладень та пошуку найближчої події. Наприклад, при розробці календарного додатка можна перевірити, чи перетинається нова подія з існуючими. Клас Interval підтримує операції contains, overlaps, gap та abuts — остання показує, чи стосуються інтервали межами. Для вимірювання тривалості між двома моментами використовується Duration з точністю до мілісекунд.

java
// Перевірити перекриття інтервалів
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); // true
Duration gap = meeting1.gap(meeting2); // null (немає прогалину)

Часто задавані питання

Що таке Joda-Time і навіщо вона потрібна?

Joda-Time — бібліотека для роботи з датами та часом в Java, створена до виходу Java 8. Вона виправляла недоліки java.util.Date та java.util.Calendar: мутабельність, нумерацію місяців з 0, відсутність повноцінної підтримки часових поясів та потоконебезпечне форматування.

Чим Joda-Time відрізняється від java.time?

Java.time (JSR-310) — наступник Joda-Time, розроблений тим же автором. Основні відмінності: java.time вбудований в стандартну бібліотеку Java 8+, використовує більш послідовну систему назв, підтримує альтернативні календарні системи та включає клас Instant для роботи з UTC-часом.

Чи варто використовувати Joda-Time в нових проектах?

Ні, для нових проектів рекомендується використовувати java.time. Joda-Time знаходиться в режимі підтримки з 2014 року та більше не отримує нових можливостей. Для Android з API 26+ java.time доступний нативно, а для старіших версій використовується desugaring — механізм, що дозволяє використовувати java.time на пристроях з API 19+.

Як мігрувати код з Joda-Time на java.time?

Міграція виконується поэтапно: ізолюйте Joda-Time в абстракції, замініть LocalDate та LocalTime першими, потім DateTime → ZonedDateTime, і на останньому етапі — Period, Duration та Interval. Інструмент OpenRewrite підтримує автоматичну міграцію через рецепт JodaTimeToJavaTime, що прискорює процес в 2–3 рази.

Які класи Joda-Time відповідають java.time?

DateTime → ZonedDateTime, LocalDate → LocalDate (збігається), LocalTime → LocalTime, LocalDateTime → LocalDateTime, DateTimeZone → ZoneId, Interval → відсутній прямий аналог (використовується комбінація Instant + Duration), Period → Period, Duration → Duration. Назви методів також близькі: plusDays, minusMonths, withZone доступні в обох бібліотеках.

Підсумки

  • Joda-Time — бібліотека дат та часу для Java, яка стала стандартом до виходу Java 8 та прямо повплинала на специфікацію JSR-310
  • Immutable-дизайн — всі класи Joda-Time незмінні, що гарантує потокобезпеку та запобігає випадковій мутації об’єктів
  • Ключові класи — DateTime, LocalDate, LocalTime, LocalDateTime, Period, Duration та Interval покривають усі сценарії роботи з датами та часом
  • Підтримка часових поясів — вбудована база 200+ поясів з автоматичною обробкою переходу на літній час та оновленнями
  • Міграція на java.time — рекомендується для всіх проектів; виконується поэтапно, з використанням інструментів OpenRewrite та вбудованих засобів IDE
  • Android-сумісність — Joda-Time працює від API 1, але для API 26+ краще java.time, доступний через desugaring на старіших версіях
  • Історичне значення — Joda-Time змінила підхід до проектування API в Java та демонструвала спільноті переваги іммутабельних value-об’єктів

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також