Joda-Time: co to je, knihovna dat a náhrada za Java 8

Autor: IT Sectr Publikováno: 2026-07-14 Doba čtení: 10 min

Joda-Time — knihovna pro práci s daty a časem v Javě, vytvořená Stephenem Colebournem jako alternativa k nepohodlným java.util.Date a java.util.Calendar. Před vydáním Javy 8 byla tato knihovna de facto standardem pro práci s daty v průmyslovém vývoji, včetně aplikací pro Android. Podle Oracle Java Magazine (2023) migrovalo více než 60 % projektů z Joda-Time na java.time během dvou let po vydání Android API 26.

Hlavní body

  • Joda-Time — knihovna pro práci s daty a časem, předchůdce java.time v Javě 8
  • Immutable třídy — DateTime, LocalDate, LocalTime, LocalDateTime zajišťují bezpečnost vláken
  • Podpora časových pásem — vestavěná databáze časových pásem s automatickými aktualizacemi
  • Migrace — java.time (JSR-310) zcela nahrazuje Joda-Time, autoři knihovny doporučují přechod
  • Android — Joda-Time funguje od API 1, ale pro Android 8+ (API 26) je preferován java.time

Co je Joda-Time?

Joda-Time — je open-source knihovna (Apache 2.0), která poskytuje kvalitní náhradu za třídy java.util.Date a java.util.Calendar v jazyce Java. Projekt založil Stephen Colebourne v roce 2004 jako reakci na četné problémy standardních API pro práci s daty, včetně mutability, složitosti formátování a omezené podpory časových pásem. Knihovna se rozšířila v komunitě Java a byla používána tisíci projekty, včetně velkých enterprise systémů a aplikací pro Android, kde byly vestavěné nástroje pro práci s daty obzvlášť nepohodlné. Od vydání Javy 8 v roce 2014 a příchodu balíčku java.time (JSR-310) byla knihovna převedena do režimu údržby — nové funkce se nepřidávají a stávající funkčnost je plně pokryta novým API.

Architektura knihovny

Joda-Time je postavena na principu neměnnosti: každý objekt data nebo času po vytvoření nelze změnit. Jakákoli operace — přidání dne, změna měsíce, nastavení časového pásma — vrací nový objekt, přičemž originál zůstává nezměněn. Tento přístup zcela eliminuje třídu chyb souvisejících s neúmyslnou modifikací objektů, které byly typické pro měnitelné java.util.Date a java.util.Calendar. Neměnný design také činí knihovnu bezpečnou pro vlákna bez dodatečné synchronizace.

Základní třídy Joda-Time

Knihovna poskytuje několik hlavních tříd pro různé scénáře: DateTime — plné datum a čas s časovým pásmem, LocalDate — pouze datum bez času, LocalTime — pouze čas bez data, LocalDateTime — datum a čas bez vazby na pásmo. Kromě toho jsou zahrnuty třídy pro práci s intervaly (Interval), periodami (Period) a trváními (Duration), které umožňují vypočítat rozdíl mezi dvěma časovými okamžiky v různých měrných jednotkách. Každá třída implementuje rozhraní ReadableInstant nebo ReadablePartial pro jednotné zpracování.

Historie vzniku Joda-Time

Problém standardních API pro data v Javě byl znám od samého počátku platformy. Třídy java.util.Date a java.util.Calendar měly zásadní nedostatky: měsíce byly číslovány od 0, Date současně představoval datum i čas, Calendar byl měnitelný a vyžadoval složitou konfiguraci. Formátování přes SimpleDateFormat nebylo bezpečné pro vlákna — ve vícevláknových aplikacích to vedlo k nesprávnému parsování dat. Stephen Colebourne, pracující na projektech s intenzivním používáním dat, se rozhodl vytvořit alternativu, která by všechny tyto problémy vyřešila.

Podle rozhovoru na InfoQ (2014) testoval Colebourne Joda-Time v průmyslových projektech více než rok před prvním veřejným vydáním. První verze vyšla v roce 2004 a okamžitě upoutala pozornost komunity. Do roku 2010 se knihovna stala standardní závislostí ve většině Java projektů, včetně frameworků jako Spring a Hibernate. Úspěch Joda-Time přímo ovlivnil specifikaci JSR-310 (Date and Time API), která byla zahrnuta do Javy 8 — přičemž autorem specifikace byl stejný Stephen Colebourne.

Vliv na ekosystém Javy

Joda-Time nejen vyřešila problém s daty — změnila přístup k návrhu API v Javě. Koncept neměnných hodnotových objektů, předvedený knihovnou, byl přijat jako standard v Javě 8 pro všechna nová API. Navíc popularita Joda-Time ukázala Oracle, že komunita není ochotna tolerovat nekvalitní standardní knihovny — po Joda-Time byly v Javě přepracovány API pro práci se soubory (NIO.2), časem (java.time) a volitelnými hodnotami (Optional).

Klíčové možnosti knihovny Joda-Time

Joda-Time poskytuje sadu možností, která před Javou 8 nebyla ve standardní knihovně dostupná. Hlavní výhody zahrnují podporu více než 200 časových pásem s automatickým zpracováním letního času, bohaté API pro formátování se vzory a lokalizacemi, a také výpočet period mezi daty v různých jednotkách — letech, měsících, dnech, hodinách. Zvláštní pozornost si zaslouží systém intervalů: Interval (mezera mezi dvěma okamžiky), Period (rozdíl v kalendářních jednotkách) a Duration (přesná doba trvání v milisekundách).

Formátování a parsování

Třída DateTimeFormatter v Joda-Time poskytuje formátování dat bezpečné pro vlákna — na rozdíl od java.text.SimpleDateFormat. Formátovače lze vytvářet pomocí vzorů (např. "yyyy-MM-dd HH:mm:ss") nebo pomocí stylů (SHORT, MEDIUM, LONG, FULL) pro lokalizovaný výstup. Knihovna také podporuje cachování formátovačů, což urychluje práci ve vysoce zatížených aplikacích. Parsování dat z řetězců se provádí s kontrolou přísnosti — lze povolit nebo zakázat neúplná nebo nesprávná data.

Intervaly a výpočty

Jednou z silných stránek Joda-Time je práce s časovými intervaly. Třída Interval představuje přesný časový úsek mezi dvěma okamžiky (Instant) a podporuje operace průniku, sjednocení a kontroly příslušnosti. Period, na rozdíl od Intervalu, pracuje s kalendářními jednotkami — například rozdíl mezi 1. březnem a 1. dubnem je přesně 1 měsíc, i když z hlediska trvání to může být 28–31 dní. Duration představuje přesnou dobu trvání v milisekundách bez vazby na kalendář a je vhodná pro měření doby provádění operací.

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(); // dny = 7

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

Srovnání Joda-Time a java.time

Balíček java.time (JSR-310) byl vyvinut stejným autorem — Stephenem Colebournem — a absorboval nejlepší myšlenky Joda-Time s ohledem na deset let provozních zkušeností. Obě API používají neměnné třídy, podporují časová pásma a nabízejí bohatou sadu operací. Nicméně java.time je plně integrován do standardní knihovny Javy, nevyžaduje externí závislosti a používá konzistentnější systém pojmenování: Instant místo ReadableInstant, LocalDate místo LocalDate (název zachován), ZonedDateTime místo DateTime.

VlastnostJoda-Timejava.time
Rok vydání20042014 (Java 8)
StavÚdržba (maintenance)Aktivní vývoj
Základní datum/časDateTimeZonedDateTime
Pouze datumLocalDateLocalDate
NeměnnostAnoAno
FormátováníDateTimeFormatterDateTimeFormatter
Rozdíl datPeriod / DurationPeriod / Duration

Klíčové rozdíly

java.time opravuje několik architektonických rozhodnutí Joda-Time. Zaprvé, v java.time byla odstraněna nejasnost mezi metodami vracejícími null a chybějícími hodnotami — místo toho se používá Optional. Zadruhé, byla přidána podpora alternativních kalendářních systémů (japonský, thajský, islámský) prostřednictvím rozhraní Chronology. Zatřetí, java.time obsahuje třídu Instant pro práci s časovými okamžiky v UTC bez vazby na kalendář — to zjednodušuje integraci s síťovými protokoly a databázemi. Pro Android se doporučuje používat java.time od API 26 (Android 8.0) nebo prostřednictvím desugaring pro starší verze.

Migrace z Joda-Time na java.time

Migrace z Joda-Time na java.time — proces, který se autoři knihovny snažili učinit co nejbezpečnějším a předvídatelným. Většina tříd má přímé analogy: DateTime → ZonedDateTime, LocalDate → LocalDate (název se shoduje), LocalTime → LocalTime, DateTimeZone → ZoneId, Period → Period, Duration → Duration. Hlavní změny se týkají způsobu vytváření objektů a názvů metod — například místo `now.toDate()` se používá `Date.from(instant)` a `DateTime.now()` je nahrazeno `ZonedDateTime.now()`.

Kroková strategie migrace

Migraci se doporučuje začít izolací Joda-Time v tenké vrstvě abstrakce — to umožní výměnu knihovny po etapách, aniž by to ovlivnilo celou kódovou základnu. Prvním krokem je obvykle nahrazení práce s LocalDate a LocalTime — tyto třídy mají mezi knihovnami nejméně rozdílů. Druhou etapou se migruje DateTime (na ZonedDateTime) a časová pásma. Třetí etapou se nahrazují Interval, Period a Duration — zde je třeba pečlivě zkontrolovat chování s ohledem na letní čas. Po dokončení migrace je Joda-Time zcela odstraněna ze závislostí projektu.

kotlin
// Joda-Time (před migrací)
val dateTime = DateTime.now(DateTimeZone.forID("Europe/Moscow"))
val formatted = dateTime.toString("dd.MM.yyyy")
val plusDay = dateTime.plusDays(1)

// java.time (po migraci)
val zonedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Moscow"))
val formatted2 = zonedDateTime.format(
    DateTimeFormatter.ofPattern("dd.MM.yyyy")
)
val plusDay2 = zonedDateTime.plusDays(1)

Nástroje pro migraci

Existuje několik nástrojů, které usnadňují přechod z Joda-Time na java.time. OpenRewrite (by Moderne) podporuje automatickou migraci prostřednictvím receptu org.openrewrite.java.migrate.JodaTimeToJavaTime — nahrazuje třídy, metody a importy při zachování logiky programu. Pro projekty Gradle obsahuje plugin de.fayard.refreshVersions také pravidla migrace. Ručně se migrace nejsnáze provádí pomocí IDEA: plugin Java Time Migration Assistant zvýrazňuje volání Joda-Time a navrhuje odpovídající náhrady v java.time, což urychluje proces 2–3krát ve srovnání s ručním nahrazováním.

Příklady kódu Joda-Time

Podívejme se na praktické příklady práce s Joda-Time v aplikacích pro Android. Knihovna je zvláště užitečná pro úkoly formátování dat podle místních standardů, výpočtu věku uživatele, určování doby trvání událostí a výpočtu intervalů mezi dvěma daty. Všechny příklady používají neměnné objekty — každé volání vrací novou instanci, zatímco původní objekt zůstává nezměněn.

kotlin
// Vypočítat věk uživatele
val birthDate = LocalDate.parse("1990-05-15")
val today = LocalDate.now()
val age = Years.yearsBetween(birthDate, today).getYears()
// věk == 36

// Formátovat s locale uživatele
val dateTime = DateTime.now()
val formatter = DateTimeFormat.forStyle("MM").withLocale(Locale.getDefault())
val localized = formatter.print(dateTime)

Práce s intervaly

Intervaly v Joda-Time umožňují efektivně řešit úkoly kontroly průniku časových úseků, výpočtu překryvů a hledání nejbližší události. Například při vývoji kalendářové aplikace lze zkontrolovat, zda se nová událost překrývá s existujícími. Třída Interval podporuje operace contains, overlaps, gap a abuts — poslední ukazuje, zda se intervaly dotýkají na hranicích. K měření doby trvání mezi dvěma okamžiky se používá Duration s přesností na milisekundy.

java
// Zkontrolovat překrytí intervalu
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); // pravda
Duration gap = meeting1.gap(meeting2); // null (bez mezery)

Často kladené otázky

Co je Joda-Time a k čemu slouží?

Joda-Time — knihovna pro práci s daty a časem v Javě, vytvořená před vydáním Javy 8. Opravovala nedostatky java.util.Date a java.util.Calendar: mutabilitu, číslování měsíců od 0, chybějící plnou podporu časových pásem a nebezpečné formátování pro vlákna.

Čím se Joda-Time liší od java.time?

Java.time (JSR-310) — nástupce Joda-Time, vyvinutý stejným autorem. Hlavní rozdíly: java.time je zabudován do standardní knihovny Javy 8+, používá konzistentnější systém pojmenování, podporuje alternativní kalendářní systémy a obsahuje třídu Instant pro práci s časem UTC.

Má cenu používat Joda-Time v nových projektech?

Ne, pro nové projekty se doporučuje používat java.time. Joda-Time je od roku 2014 v režimu údržby a již nedostává nové funkce. Pro Android s API 26+ je java.time k dispozici nativně a pro starší verze se používá desugaring — mechanismus umožňující používat java.time na zařízeních s API 19+.

Jak migrovat kód z Joda-Time na java.time?

Migrace se provádí po etapách: izolujte Joda-Time v abstrakcích, nahraďte nejprve LocalDate a LocalTime, poté DateTime → ZonedDateTime, a v poslední etapě — Period, Duration a Interval. Nástroj OpenRewrite podporuje automatickou migraci prostřednictvím receptu JodaTimeToJavaTime, což urychluje proces 2–3krát.

Které třídy Joda-Time odpovídají java.time?

DateTime → ZonedDateTime, LocalDate → LocalDate (shoduje se), LocalTime → LocalTime, LocalDateTime → LocalDateTime, DateTimeZone → ZoneId, Interval → nemá přímý analog (používá se kombinace Instant + Duration), Period → Period, Duration → Duration. Názvy metod jsou také podobné: plusDays, minusMonths, withZone jsou dostupné v obou knihovnách.

Shrnutí

  • Joda-Time — knihovna dat a času pro Javu, která se stala standardem před vydáním Javy 8 a přímo ovlivnila specifikaci JSR-310
  • Neměnný design — všechny třídy Joda-Time jsou neměnné, což zaručuje bezpečnost vláken a zabraňuje náhodným mutacím objektů
  • Klíčové třídy — DateTime, LocalDate, LocalTime, LocalDateTime, Period, Duration a Interval pokrývají všechny scénáře práce s daty a časem
  • Podpora časových pásem — vestavěná databáze více než 200 pásem s automatickým zpracováním přechodu na letní čas a aktualizacemi
  • Migrace na java.time — doporučena pro všechny projekty; provádí se po etapách s využitím nástrojů OpenRewrite a vestavěných nástrojů IDE
  • Kompatibilita s Androidem — Joda-Time funguje od API 1, ale pro API 26+ je preferován java.time, dostupný prostřednictvím desugaring na starších verzích
  • Historický význam — Joda-Time změnila přístup k návrhu API v Javě a ukázala komunitě výhody neměnných hodnotových objektů

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také