Joda-Time ist eine Bibliothek zum Arbeiten mit Datums- und Zeitangaben in Java, erstellt von Stephen Colebourne als Alternative zu den umständlichen java.util.Date und java.util.Calendar. Vor der Veröffentlichung von Java 8 war diese Bibliothek der De-facto-Standard für die Datumsverarbeitung in der industriellen Entwicklung, einschließlich Android-Anwendungen. Laut Oracle Java Magazine (2023) sind über 60 % der Projekte innerhalb von zwei Jahren nach der Veröffentlichung von Android API 26 von Joda-Time zu java.time migriert.
Wichtige Erkenntnisse
Joda-Time ist eine Open-Source-Bibliothek (Apache 2.0), die einen qualitativ hochwertigen Ersatz für die Klassen java.util.Date und java.util.Calendar in Java bietet. Das Projekt wurde 2004 von Stephen Colebourne als Reaktion auf zahlreiche Probleme der Standard-Datums- und Zeit-APIs gegründet, darunter Veränderbarkeit, Formatierungskomplexität und eingeschränkte Zeitzonenunterstützung. Die Bibliothek fand breite Akzeptanz in der Java-Community und wurde in Tausenden von Projekten eingesetzt, darunter große Unternehmenssysteme und Android-Anwendungen, bei denen die integrierten Datumsverarbeitungswerkzeuge besonders umständlich waren. Seit der Veröffentlichung von Java 8 im Jahr 2014 und der Einführung des java.time-Pakets (JSR-310) wurde die Bibliothek in den Wartungsmodus versetzt — es werden keine neuen Funktionen hinzugefügt und die vorhandene Funktionalität wird vollständig von der neuen API abgedeckt.
Joda-Time basiert auf dem Prinzip der Unveränderlichkeit: Jedes Datums- oder Zeitobjekt kann nach der Erstellung nicht mehr geändert werden. Jeder Vorgang — Hinzufügen eines Tages, Ändern eines Monats, Festlegen einer Zeitzone — gibt ein neues Objekt zurück, während das Original unverändert bleibt. Dieser Ansatz beseitigt vollständig die Klasse von Fehlern, die mit unbeabsichtigten Objektänderungen verbunden sind, die für die veränderlichen java.util.Date und java.util.Calendar charakteristisch waren. Das unveränderliche Design macht die Bibliothek auch ohne zusätzliche Synchronisation threadsicher.
Die Bibliothek bietet mehrere Hauptklassen für verschiedene Szenarien: DateTime — vollständiges Datum und Uhrzeit mit Zeitzone, LocalDate — nur Datum ohne Uhrzeit, LocalTime — nur Uhrzeit ohne Datum, LocalDateTime — Datum und Uhrzeit ohne Zeitzonenbindung. Darüber hinaus sind Klassen für die Arbeit mit Intervallen (Interval), Zeiträumen (Period) und Dauern (Duration) enthalten, mit denen Sie die Differenz zwischen zwei Zeitpunkten in verschiedenen Maßeinheiten berechnen können. Jede Klasse implementiert das ReadableInstant- oder ReadablePartial-Interface für eine einheitliche Handhabung.
Das Problem mit den Standard-Datums-APIs in Java war seit den Anfängen der Plattform bekannt. Die Klassen java.util.Date und java.util.Calendar hatten grundlegende Mängel: Monate wurden ab 0 nummeriert, Date repräsentierte gleichzeitig Datum und Uhrzeit, Calendar war veränderlich und erforderte eine komplexe Konfiguration. Die Formatierung über SimpleDateFormat war nicht threadsicher — in Multithread-Anwendungen führte dies zu falscher Datumsanalyse. Stephen Colebourne, der an Projekten mit intensiver Datumsnutzung arbeitete, beschloss, eine Alternative zu schaffen, die all diese Probleme beheben würde.
Laut einem Interview auf InfoQ (2014) testete Colebourne Joda-Time über ein Jahr lang in Produktionsprojekten, bevor die erste öffentliche Version veröffentlicht wurde. Die erste Version wurde 2004 veröffentlicht und zog sofort die Aufmerksamkeit der Community auf sich. Bis 2010 war die Bibliothek in den meisten Java-Projekten, einschließlich Frameworks wie Spring und Hibernate, zur Standardabhängigkeit geworden. Der Erfolg von Joda-Time beeinflusste direkt die JSR-310-Spezifikation (Date and Time API), die in Java 8 enthalten war — mit demselben Stephen Colebourne als Spezifikationsleiter.
Joda-Time löste nicht nur das Datumsproblem — es veränderte den Ansatz zum API-Design in Java. Das Konzept der unveränderlichen Wertobjekte, das von der Bibliothek demonstriert wurde, wurde in Java 8 als Standard für alle neuen APIs übernommen. Darüber hinaus zeigte die Popularität von Joda-Time Oracle, dass die Community nicht bereit war, minderwertige Standardbibliotheken zu akzeptieren — nach Joda-Time wurden die Java-APIs für Dateiverwaltung (NIO.2), Zeit (java.time) und optionale Werte (Optional) überarbeitet.
Joda-Time bietet eine Reihe von Funktionen, die in der Standardbibliothek vor Java 8 nicht verfügbar waren. Zu den wichtigsten Vorteilen gehören Unterstützung für über 200 Zeitzonen mit automatischer Sommerzeitbehandlung, eine umfangreiche Formatierungs-API mit Mustern und Gebietsschemata sowie die Berechnung von Zeiträumen zwischen Daten in verschiedenen Einheiten — Jahren, Monaten, Tagen, Stunden. Besonders erwähnenswert ist das Intervallsystem: Interval (eine Spanne zwischen zwei Zeitpunkten), Period (Unterschied in Kalendereinheiten) und Duration (genaue Länge in Millisekunden).
Die Klasse DateTimeFormatter in Joda-Time bietet threadsichere Datumsformatierung — im Gegensatz zu java.text.SimpleDateFormat. Formatierer können über Muster (z. B. „yyyy-MM-dd HH:mm:ss“) oder über Stile (SHORT, MEDIUM, LONG, FULL) für lokalisierte Ausgabe erstellt werden. Die Bibliothek unterstützt auch das Caching von Formatierern, was die Leistung in stark ausgelasteten Anwendungen verbessert. Das Parsen von Datumsangaben aus Zeichenfolgen erfolgt mit strikter Kontrolle — Sie können unvollständige oder falsche Daten zulassen oder ablehnen.
Eine der Stärken von Joda-Time ist die Arbeit mit Zeitintervallen. Die Klasse Interval repräsentiert eine genaue Zeitspanne zwischen zwei Zeitpunkten und unterstützt Operationen wie Schnittmenge, Vereinigung und Enthaltenseinsprüfung. Period arbeitet im Gegensatz zu Interval in Kalendereinheiten — zum Beispiel beträgt der Unterschied zwischen dem 1. März und dem 1. April genau 1 Monat, obwohl es in der Dauer 28–31 Tage sein können. Duration hingegen repräsentiert eine genaue Länge in Millisekunden ohne Kalenderbindung und eignet sich zur Messung der Ausführungszeit von Operationen.
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(); // Tage = 7
Interval interval = new Interval(now, nextWeek);
boolean contains = interval.contains(now); // wahr
Das java.time-Paket (JSR-310) wurde vom gleichen Autor — Stephen Colebourne — entwickelt und enthält die besten Ideen von Joda-Time mit zehn Jahren Betriebserfahrung. Beide APIs verwenden unveränderliche Klassen, unterstützen Zeitzonen und bieten eine reichhaltige Palette an Operationen. Allerdings ist java.time vollständig in die Java-Standardbibliothek integriert, benötigt keine externen Abhängigkeiten und verwendet ein konsistenteres Benennungssystem: Instant statt ReadableInstant, LocalDate statt LocalDate (Name beibehalten), ZonedDateTime statt DateTime.
| Eigenschaft | Joda-Time | java.time |
|---|---|---|
| Veröffentlichungsjahr | 2004 | 2014 (Java 8) |
| Status | Wartung | Aktive Entwicklung |
| Basis Datum/Zeit | DateTime | ZonedDateTime |
| Nur Datum | LocalDate | LocalDate |
| Unveränderlichkeit | Ja | Ja |
| Formatierung | DateTimeFormatter | DateTimeFormatter |
| Datumsdifferenz | Period / Duration | Period / Duration |
java.time behebt mehrere architektonische Entscheidungen von Joda-Time. Erstens beseitigt java.time die Verwirrung zwischen Methoden, die null zurückgeben, und fehlenden Werten — stattdessen wird Optional verwendet. Zweitens wurde über das Chronology-Interface Unterstützung für alternative Kalendersysteme (japanisch, thailändisch, islamisch) hinzugefügt. Drittens enthält java.time die Klasse Instant für die Arbeit mit UTC-Zeitpunkten ohne Kalenderbindung — dies vereinfacht die Integration mit Netzwerkprotokollen und Datenbanken. Für Android wird die Verwendung von java.time ab API 26 (Android 8.0) oder über Desugaring für ältere Versionen empfohlen.
Die Migration von Joda-Time zu java.time ist ein Prozess, den die Autoren der Bibliothek so sicher und vorhersagbar wie möglich gestalten wollten. Die meisten Klassen haben direkte Entsprechungen: DateTime → ZonedDateTime, LocalDate → LocalDate (Name stimmt überein), LocalTime → LocalTime, DateTimeZone → ZoneId, Period → Period, Duration → Duration. Die wichtigsten Änderungen betreffen die Art und Weise, wie Objekte erstellt werden, und die Methodennamen — zum Beispiel wird statt `now.toDate()` `Date.from(instant)` verwendet und `DateTime.now()` durch `ZonedDateTime.now()` ersetzt.
Es wird empfohlen, die Migration zu beginnen, indem Joda-Time in einer dünnen Abstraktionsschicht isoliert wird — dies ermöglicht den schrittweisen Austausch der Bibliothek, ohne die gesamte Codebasis zu berühren. Der erste Schritt besteht normalerweise darin, die Arbeit mit LocalDate und LocalTime zu ersetzen — diese Klassen weisen die wenigsten Unterschiede zwischen den Bibliotheken auf. In der zweiten Phase werden DateTime (zu ZonedDateTime) und Zeitzonen migriert. In der dritten Phase werden Interval, Period und Duration ersetzt — hier müssen Sie das Sommerzeitverhalten sorgfältig überprüfen. Nach Abschluss der Migration wird Joda-Time vollständig aus den Projektabhängigkeiten entfernt.
// Joda-Time (vor der Migration)
val dateTime = DateTime.now(DateTimeZone.forID("Europe/Moscow"))
val formatted = dateTime.toString("dd.MM.yyyy")
val plusDay = dateTime.plusDays(1)
// java.time (nach der Migration)
val zonedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Moscow"))
val formatted2 = zonedDateTime.format(
DateTimeFormatter.ofPattern("dd.MM.yyyy")
)
val plusDay2 = zonedDateTime.plusDays(1)
Es gibt mehrere Hilfsprogramme, die den Übergang von Joda-Time zu java.time vereinfachen. OpenRewrite (von Moderne) unterstützt die automatische Migration über das Rezept org.openrewrite.java.migrate.JodaTimeToJavaTime — es ersetzt Klassen, Methoden und Importe, wobei die Programmlogik erhalten bleibt. Für Gradle-Projekte enthält das Plugin de.fayard.refreshVersions ebenfalls Migrationsregeln. Manuell ist die Migration am einfachsten mit IDEA durchzuführen: Das Plugin Java Time Migration Assistant hebt Joda-Time-Aufrufe hervor und schlägt entsprechende Ersetzungen in java.time vor, was den Prozess im Vergleich zur manuellen Ersetzung um das 2- bis 3-fache beschleunigt.
Sehen wir uns praktische Beispiele für die Arbeit mit Joda-Time in Android-Anwendungen an. Die Bibliothek ist besonders nützlich zum Formatieren von Daten nach lokalen Standards, zum Berechnen des Benutzeralters, zum Bestimmen der Ereignisdauer und zum Berechnen von Intervallen zwischen zwei Daten. Alle Beispiele verwenden unveränderliche Objekte — jeder Aufruf gibt eine neue Instanz zurück, während das ursprüngliche Objekt unverändert bleibt.
// Benutzeralter berechnen
val birthDate = LocalDate.parse("1990-05-15")
val today = LocalDate.now()
val age = Years.yearsBetween(birthDate, today).getYears()
// Alter == 36
// Mit Benutzergebietsschema formatieren
val dateTime = DateTime.now()
val formatter = DateTimeFormat.forStyle("MM").withLocale(Locale.getDefault())
val localized = formatter.print(dateTime)
Intervalle in Joda-Time ermöglichen es, Aufgaben wie die Überprüfung von Zeitintervallüberlappungen, die Berechnung von Überschneidungen und die Suche nach dem nächsten Ereignis effizient zu lösen. Bei der Entwicklung einer Kalenderanwendung können Sie beispielsweise überprüfen, ob ein neues Ereignis mit vorhandenen überlappt. Die Klasse Interval unterstützt die Operationen contains, overlaps, gap und abuts — letztere zeigt an, ob sich Intervalle an ihren Grenzen berühren. Duration wird verwendet, um die Länge zwischen zwei Zeitpunkten mit Millisekundengenauigkeit zu messen.
// Intervallüberlappung prüfen
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); // wahr
Duration gap = meeting1.gap(meeting2); // null (keine Lücke)
Häufig gestellte Fragen
Joda-Time ist eine Bibliothek zum Arbeiten mit Datums- und Zeitangaben in Java, die vor der Veröffentlichung von Java 8 erstellt wurde. Sie behob die Mängel von java.util.Date und java.util.Calendar: Veränderbarkeit, Nummerierung der Monate ab 0, fehlende vollständige Zeitzonenunterstützung und nicht threadsichere Formatierung.
Java.time (JSR-310) ist der Nachfolger von Joda-Time, entwickelt vom gleichen Autor. Die Hauptunterschiede: java.time ist in die Java 8+ Standardbibliothek integriert, verwendet ein konsistenteres Benennungssystem, unterstützt alternative Kalendersysteme und enthält die Klasse Instant für die Arbeit mit UTC-Zeit.
Nein, für neue Projekte wird die Verwendung von java.time empfohlen. Joda-Time befindet sich seit 2014 im Wartungsmodus und erhält keine neuen Funktionen mehr. Für Android mit API 26+ ist java.time nativ verfügbar, und für ältere Versionen wird Desugaring verwendet — ein Mechanismus, der die Verwendung von java.time auf Geräten mit API 19+ ermöglicht.
Die Migration erfolgt schrittweise: Isolieren Sie Joda-Time in Abstraktionen, ersetzen Sie zuerst LocalDate und LocalTime, dann DateTime → ZonedDateTime und schließlich Period, Duration und Interval. Das Tool OpenRewrite unterstützt die automatische Migration über das Rezept JodaTimeToJavaTime und beschleunigt den Prozess um das 2- bis 3-fache.
DateTime → ZonedDateTime, LocalDate → LocalDate (übereinstimmend), LocalTime → LocalTime, LocalDateTime → LocalDateTime, DateTimeZone → ZoneId, Interval → kein direktes Äquivalent (eine Kombination aus Instant + Duration wird verwendet), Period → Period, Duration → Duration. Auch die Methodennamen sind ähnlich: plusDays, minusMonths, withZone sind in beiden Bibliotheken verfügbar.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch