Migration von Joda-Time zu java.time
Die Migration von Code (sprich: Legacy-Code) macht keinen Spaß. Es erfordert enorm viel Planung und Aufwand, um dies erfolgreich umzusetzen. Auch wenn es für Entwickler nicht die aufregendste oder motivierendste Aufgabe ist, erfordert die Migration von Legacy-Code auf neue Bibliotheksversionen Entschlossenheit und die richtige Erfahrung. Joda-Time zu java.time ist eine solche Migration, die eine sorgfältige Planung und Ausführung erfordert.
Wenn Ihr Java-Projekt vor Java SE 8 entstanden ist und Datums-/Zeitverarbeitung nutzt, wurde wahrscheinlich Joda-Time verwendet – eine hervorragende Bibliothek und der De-facto-Standard für Datums- und Zeitfunktionen vor SE 8. Wenn Ihr Projekt immer noch Joda-Time verwendet, Sie aber zu java.time migrieren möchten, lesen Sie weiter.
Die Veröffentlichung von Java SE 8 enthielt eine neue und verbesserte Standard-Date-and-Time-API, die allgemein als java.time (JSR-310) bezeichnet wird. Das Joda-Time-Projekt empfiehlt mittlerweile die Migration zu java.time (JSR-310).
Obwohl java.time (JSR-310) stark von Joda-Time inspiriert wurde, ist es nicht abwärtskompatibel und Konzepte sowie Terminologien haben sich geändert. Deshalb erfordert die Migration von Joda-Time zu java.time bei jeder einzelnen Codezeile, die Sie ändern, größte Aufmerksamkeit. Dies kann zeitaufwendig sein und lässt einen fast wünschen, es gäbe einen einfacheren und automatisierten Weg für die Migration.
Es gibt einen besseren Weg für die Migration, und wir haben ihn mit Sensei geschaffen – einem IntelliJ-Plugin, das Code-Transformationen automatisch gemäß den von Ihnen definierten Rezepten (Regeln) durchführt. Investieren Sie Ihre Zeit in die Definition wiederverwendbarer Rezepte, anstatt sich mit repetitiven Migrationsaufgaben zu befassen. Die Automatisierung transformiert nicht nur Ihren alten Joda-Time-Code, sondern hilft Teams auch dabei, die Richtlinien direkt in der IDE einzuhalten, während sie neuen Code schreiben.
Um Ihnen den Einstieg zu erleichtern, haben wir ein öffentliches Sensei-Kochbuch erstellt: Standardisierung auf java.time (JSR-310), das Rezepte enthält, um die Migration von Joda-Time zu java.time weniger schmerzhaft zu gestalten. Dies ist eine wachsende Sammlung von Rezepten, die wir kontinuierlich erweitern werden, um eine noch größere Abdeckung zu erreichen.
Hier ist ein Beispiel für eine Migration, das Ihnen verdeutlicht, wie Sensei die Migration von Legacy-Code mühelos macht.

Von manueller, repetitiver Migration zu automatisierten Code-Transformationen
Schauen wir uns ein Beispiel für die Erstellung eines neuen DateTime an, das einige versteckte Fallstricke bei der Migration einer einzelnen Codezeile von Joda-Time zu java.time aufzeigt. Wir betrachten dann eines unserer Sensei-Rezepte aus unserem Kochbuch zur Standardisierung auf java.time (JSR-310) und zeigen, wie es all diese Informationen erfasst, sodass dieselbe Migration von jedem Entwickler immer wieder verwendet werden kann.
In diesem Beispiel konstruieren wir ein Joda-Time DateTime aus 7 Integer-Argumenten, die die Werte der DateTime-Felder repräsentieren.
Wie migrieren wir dies zu einem java.time-Äquivalent?
Das Javadoc in Joda-Time für diesen Konstruktor besagt:
Konstruiert eine Instanz aus Datums-/Zeitfeldwerten unter Verwendung von ISOChronology in der Standardzeitzone.
Zuerst könnten wir annehmen, dass es eine DateTime-Klasse in java.time gibt, aber das ist nicht der Fall. Wenn Sie nach „migrate from joda time to java time“ googeln, werden Sie höchstwahrscheinlich auf den Blogbeitrag von Stephen Colebourne Converting from Joda-Time to java.time stoßen.
Dies ist ein guter Anfang und weist uns in die Richtung, java.time.ZonedDateTime oder java.time.OffsetDateTime zu verwenden. Hier ist unsere erste Frage: Was davon soll ich verwenden? Wahrscheinlich ZonedDateTime, basierend auf Stephens Kommentaren.
Wenn wir das ZonedDateTime-Javadoc nachschlagen, sehen wir überhaupt keine Konstruktoren. Wenn wir zu Stephens Blogbeitrag zurückkehren, lesen wir weiter unten:
Konstruktion. Joda-Time verfügt über einen Konstruktor, der ein Objekt akzeptiert und eine Typkonvertierung durchführt. java.time bietet lediglich Factory-Methoden an, weshalb die Konvertierung in der Verantwortung des Nutzers liegt, auch wenn für Strings eine parse()-Methode bereitgestellt wird.
Es muss also eine statische Factory-Methode geben. Bei der Suche nach statischen Methoden finden wir eine, die sehr passend erscheint, aber nicht exakt identisch ist.
Sie besitzt 7 int-Parameter, genau wie unser ursprünglicher Joda-Time DateTime-Konstruktor. Wenn man jedoch nicht aufpasst, übersieht man ein wichtiges Detail: Der 7. Parameter repräsentiert nicht mehr Millisekunden, sondern erwartet Nanosekunden. Das liegt daran, dass java.time eine höhere Präzision als Joda-Time aufweist und Zeitpunkte bis auf die Nanosekunde genau misst. Ein wichtiges Detail, das man leicht übersehen kann. Zudem erfordert diese Methode eine ZoneId, was die Frage aufwirft, warum man diese vorher nicht benötigte und warum sie jetzt erforderlich ist.
Wenn man sich an das Javadoc unseres ursprünglichen Konstruktors erinnert, in dem erwähnt wurde, dass die Standardzeitzone verwendet wird, gibt es vielleicht eine Möglichkeit, die Standard-ZoneId abzurufen?
The javadoc for ZoneId does not tell us about any constructors listed, but looking at the static methods we see we can use systemDefault()
Nachdem wir die ZoneId geklärt haben, stellt sich die Frage, wie wir die Umrechnung von Millisekunden in Nanosekunden handhaben. Vielleicht können wir java.util.concurrent.TimeUnit für die Konvertierung nutzen.
Diese Methode gibt einen long-Wert zurück, unsere Methode erwartet jedoch einen int-Wert, sodass wir auch hier ein Konvertierungsproblem lösen müssen. Vielleicht versuchen wir es mit etwas Einfachem: einer Multiplikation?
Das funktioniert zwar, wirkt aber etwas deplatziert. Falls es Ihnen noch nicht aufgefallen ist: Wir haben eine beachtliche Menge an Zeit und Mühe investiert, um eine einzige Zeile Code zu migrieren. Wie Sie sich vorstellen können, stehen uns viele solcher manuellen Anpassungen bevor, und es wird nicht einfacher.
Wenn wir uns jedoch die java.time-API etwas genauer ansehen, finden wir eine Lösung, die etwas flüssiger wirkt.
Obwohl es bei ZonedDateTime keinen offensichtlichen Weg gibt, die Millisekunden zu setzen, lässt sich dies über die Methode with(TemporalField field, long newValue) erreichen, indem ChronoField.MILLI_OF_SECOND als TemporalField verwendet wird.
Und das Javadoc erwähnt, dass die Umrechnung in Nanosekunden automatisch für uns durchgeführt wird:
Wenn dieses Feld zum Setzen eines Wertes verwendet wird, sollte es sich genauso verhalten, als würde NANO_OF_SECOND mit dem Wert multipliziert mit 1.000.000 gesetzt.
Wir können also einfach 0 für unsere Nanosekunden in der Factory-Methode angeben und dann die with-Methode verwenden, um ein ZonedDateTime zu erstellen, das sowohl alle ursprünglichen Werte als auch die Millisekunden enthält.
Betrachtet man das Endergebnis, sieht es so aus, als hätten wir nur eine einzige Zeile Code geändert – das spiegelt den Aufwand, der in die Recherche für nur eine einzige Migration geflossen ist, kaum wider!
Erstellen Sie ein Rezept für eine schnellere und einfachere Migration
Sensei bietet uns eine Möglichkeit, dieses hart erarbeitete Wissen mit anderen Entwicklern zu teilen. Durch die Erstellung eines Rezepts, das all diese Anforderungen erfasst, können Sensei-Nutzer diese Migration mit einem Mausklick durchführen.
Ein Sensei-Rezept besteht aus 3 Hauptabschnitten:
- Metadaten
- Suche
- VerfügbareKorrekturen
Schauen wir uns ein Sensei-Rezept an (das auch als YAML-Rezept angezeigt werden kann), das uns bei der Migration dieses Aufrufs in das entsprechende java.time-Äquivalent hilft.
DateTime foo = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond);
Metadaten-Bereich
Der Metadaten-Bereich enthält Informationen über das Rezept und dessen Verwendung.
Suchbereich
Der Suchbereich eines Sensei-Rezepts legt fest, auf welche Code-Elemente das Rezept angewendet werden soll.
search:
instanceCreation:
args:
1:
type: int
2:
type: int
3:
type: int
4:
type: int
5:
type: int
6:
type: int
7:
type: int
argCount: 7
type: org.joda.time.DateTime
In diesem Suchbereich sehen wir, dass wir:
- Nach einer instanceCreation suchen, d. h. einer Verwendung eines Konstruktors. Hinweis: Es sind viele weitere Suchziele verfügbar
- . Der Konstruktor sollte 7 Argumente haben; dies wird durch die Eigenschaft argCount festgelegt. Die
- args 1-7 sollten vom Typ int sein. Wir suchen nach Konstruktoren des
- Typs org.joda.time.DateTime
Bereich für verfügbare Korrekturen
Der Bereich „availableFixes“ kann eine oder mehrere Korrekturen festlegen, die auf das übereinstimmende Code-Element angewendet werden können. Jede Korrektur kann mehrere Aktionen umfassen; in unserem Fall haben wir eine einzelne Korrektur, die 2 Aktionen ausführt.
- Der name der Korrektur wird dem Benutzer im Menü „Quickfixes“ angezeigt und beschreibt, was passiert, wenn der Benutzer diesen Quickfix anwendet.
- Die Aktionsliste zeigt, welche Aktionen durch diesen Quickfix ausgeführt werden.
- Die rewrite-Aktion schreibt das Code-Element mithilfe einer Mustache-Vorlage um. Sie kann Variablen und String-Ersetzungsfunktionen verwenden.
- Die modifyAssignedVariable-Aktion prüft, ob dieser Konstruktor verwendet wird, um den Wert einer Variablen zuzuweisen. Falls ja, ändert diese Aktion die Deklaration der Variablen in den durch type
Verwendung des Rezepts zur Code-Transformation
Sobald unser Rezept geschrieben und aktiviert ist, scannt es unseren Code und hebt die Segmente hervor, auf die es angewendet werden kann.
Im Screenshot unten sehen wir, dass der Zielkonstruktor von Sensei markiert wurde. Wenn man mit der Maus über den markierten Konstruktor fährt, werden die „shortDescription“ des Rezepts und die Quickfix-Option Migrate to java.time.ZonedDateTime

Nachdem wir den Quickfix Migrate to java.time.ZonedDateTime ausgewählt haben, wird der Code gemäß den im Rezept festgelegten Aktionen transformiert.

Einmalige Migration und einheitliche Codierungspraktiken in Teams – mit Sensei
Wie unser Beispiel oben zeigt, kann die Migration einer einzelnen Codezeile mühsam erworbenes Wissen erfordern. Sensei verwandelt dieses Wissen in umsetzbare Rezepte oder Kochbücher, die im Team geteilt werden können. Sie können einen einmaligen Migrations-Sprint planen oder schrittweise Transformationen zu java.time vornehmen, sobald Sie auf Joda-Time-Code stoßen. Sie können Rezepte aktivieren/deaktivieren, um Migrationen in logischen Phasen durchzuführen, und sogar den Umfang der von Sensei gescannten Dateien anpassen – die Flexibilität, die Code-Migrationen weniger schmerzhaft macht.
Die Bibliotheksmigration ist nur ein Beispiel für die vielen Möglichkeiten, wie Sensei zur Standardisierung Ihrer Projekte eingesetzt werden kann. Sie können jederzeit nach Anti-Patterns oder bestimmten manuellen Code-Transformationen Ausschau halten, die Ihnen häufig in Pull Requests oder bei Ihrer eigenen Arbeit begegnen. Wenn Sie eine Reihe von Codierungsrichtlinien haben, die von Entwicklern oft übersehen werden, können Sie diese in Rezepte umwandeln – so können Entwickler genehmigte Code-Transformationen sicher anwenden.
Bei Fragen stehen wir Ihnen gerne zur Verfügung! Besuchen Sie uns auf Slack unter: sensei-scw.slack.com
Kontrollieren Sie KI-gestützte Entwicklung, bevor sie in Produktion geht
Bewerten Sie KI-gestützte Risiken, setzen Sie Richtlinien für sicheren Code direkt beim Commit durch und beschleunigen Sie die sichere Bereitstellung über Ihren gesamten SDLC hinweg.
Weitere Blogs entdecken
Erhalten Sie Zugang zu Experteninhalten über sichere Programmierung, KI-Governance und Software-Risikomanagement.
%252520%252520(3).avif)
Supercharged Security Awareness: How Tournaments are Inspiring Developers at Erste Group
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.

Security as culture: How Blue Prism cultivates world-class secure developers
Learn how Blue Prism, the global leader in intelligent automation for the enterprise, used Secure Code Warrior's agile learning platform to create a security-first culture with their developers, achieve their business goals, and ship secure code at speed

Eine Sicherheitskultur: Wie Sage sein Champions-Programm aufgebaut hat
Erfahren Sie, wie Sage die Sicherheit durch einen flexiblen, beziehungsorientierten Ansatz gestärkt, über 200 Security Champions ausgebildet und eine messbare Risikoreduzierung erzielt hat.

Cybersecurity Awareness Month 2026: Das Verständnis von KI-Sicherheit ist entscheidend für die Unternehmensverteidigung
Wir haben einen Punkt erreicht, an dem die meisten führenden KI-Unternehmen öffentlich eine weltweite Verlangsamung der KI-Entwicklung gefordert haben, damit die Sicherheitsvorkehrungen Schritt halten können. Doch die Wahrheit ist: Ernsthafte Sicherheitsprobleme sind bereits Realität geworden. Dies bringt unzählige Sicherheitsverantwortliche und Führungsteams in eine dringliche Lage, da die finanziellen Kosten und Risiken durch die Implementierung von KI stetig steigen.

Enabler 8: Branding für Ihr Programm
Ein Programm für sicheres Programmieren braucht mehr als nur großartige Inhalte, um erfolgreich zu sein. Enabler 8 zeigt, wie Branding die Teilnahme zu einem begehrten, statusorientierten Erlebnis macht.
.avif)
Jeder Mitarbeiter steht jetzt an vorderster Front der KI-Cybersicherheit
Die Unternehmenslandschaft wandelt sich mit einer Geschwindigkeit, die kaum jemand vorhergesehen hat, bis es zu spät war. Wir haben offiziell die Schwelle von handgeschriebenem Code und einfacher Copilot-Unterstützung hin zur Ära des Agentic Development Lifecycle (ADLC) überschritten. Während autonome KI-Agenten eine beispiellose Effizienz in vielen Bereichen versprechen, bringen sie auch eine völlig neue Klasse von Sicherheits- und Regulierungsrisiken mit sich.
Sichere KI-gestützte Entwicklung vor dem Release
Erkennen Sie Entwicklerrisiken, setzen Sie Richtlinien durch und verhindern Sie Schwachstellen über den gesamten Softwareentwicklungszyklus hinweg.