Migration von Joda-Time zu java.time
Das Migrieren von Code (sprich: Legacy-Code) macht keinen Spaß. Es erfordert ein enormes Maß an Planung und Mühe, um es auf den Punkt zu bringen. Es ist zwar nicht die aufregendste oder motivierendste Arbeit für Entwickler, erfordert aber Entschlossenheit und die richtige Erfahrung, um Legacy-Code auf neue Bibliotheksversionen zu migrieren. Joda-Time to java.time ist eine solche Migration, die eine sorgfältige Planung und Ausführung erfordert.
Wenn Ihr Java-Projekt vor Java SE 8 begann und Datums-/Uhrzeitverarbeitung verwendet, dann hat es wahrscheinlich Joda-Time verwendet - eine hervorragende Bibliothek und ein De-facto-Standard für die Verarbeitung von Datums- und Uhrzeitfunktionen vor SE 8. Wenn Ihr Projekt noch benutzt Joda-Time, möchte aber zu java.time migrieren, dann lies weiter.
Die Veröffentlichung von Java SE 8 enthielt eine neue und verbesserte Standard-Datums- und Uhrzeit-API, die allgemein als java.time (JSR-310) bezeichnet wird. Das Joda-Time-Projekt empfiehlt jetzt 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 und Terminologien haben sich geändert. Aus diesem Grund erfordert die Migration von Joda-Time zu java.time besondere Aufmerksamkeit bei jeder einzelnen Codezeile, die Sie ändern. Dies kann zeitaufwändig sein und Sie würden sich fast wünschen, es gäbe eine einfachere und automatisiertere Methode zur Migration.
Es gibt eine bessere Methode zur Migration und wir haben sie mit Sensei erstellt - einem IntelliJ-Plugin, das automatisch Codetransformationen gemäß den von Ihnen definierten Rezepten (Regeln) durchführt. Verbringen Sie Ihre Zeit damit, wiederverwendbare Rezepte zu definieren, anstatt sich wiederholende Migrationsaufgaben auszuführen. Die Automatisierung transformiert nicht nur Ihren alten Joda-Time-Code, sondern hilft den Teams auch dabei, die Richtlinien direkt in der IDE zu befolgen, wenn sie neuen Code schreiben.
Um Ihnen einen Vorsprung zu verschaffen, haben wir ein öffentliches Sensei-Kochbuch erstellt Standardisierung auf java.time (JSR-310) Dazu gehören Rezepte, um auf weniger schmerzhafte Weise von Joda-Time zu java.time zu migrieren. Dies ist eine wachsende Anzahl von Rezepten, die wir weiter erweitern werden, um mehr Rezepte zu bieten.
Hier ist ein Beispiel für eine Beispielmigration, anhand derer Sie sehen können, wie Sensei die Migration von Legacy-Code problemlos macht.

Von wiederholter manueller Migration bis hin zu automatisierten Codetransformationen
Schauen wir uns ein Beispiel für die Erstellung einer neuen DateTime an, die einige versteckte Fallen zeigt, wenn eine einzelne Codezeile von Joda-Time nach java.time migriert wird. Wir werden uns dann eines unserer Sensei-Rezepte aus unserem Kochbuch Standardization on java.time (JSR-310) ansehen und zeigen, wie es all diese Informationen erfasst, sodass dieselbe Migration von jedem Entwickler immer wieder verwendet werden kann.
In diesem Beispiel konstruieren wir eine Joda-Time DateTime aus 7 int-Argumenten, die Werte der DateTime-Felder darstellen.
Wie migrieren wir das auf ein java.time-Äquivalent?
Das javadoc in Joda-Time für diesen Konstruktor sagt:
Konstruiert eine Instanz aus Datetime-Feldwerten mithilfe von IsoChronology in der Standardzeitzone.
Zunächst könnten wir davon ausgehen, dass es Datum/Uhrzeit Klasse in java.time, aber es gibt keine. Wenn Sie „Von Joda Time zu Java Time migrieren“ googeln, werden Sie höchstwahrscheinlich Stephen Colebournes Blogbeitrag finden Konvertierung von Joda-Time nach java.time.
Dies gibt Ihnen einen guten Start und weist uns in die Richtung, java.time.ZonedDateTime oder java.time.OffsetDateTime zu verwenden. Hier ist unsere erste Frage, welche verwende ich? Wahrscheinlich ZonedDateTime basierend auf Stephens Kommentaren.
Ich schaue nach dem ZonedDateTime javadoc, wir können überhaupt keine Konstruktoren sehen. Zurück zu Stephens Blogbeitrag, den wir weiter unten lesen:
Baugewerbe. Joda-Time hat einen Konstruktor, der ein Objekt akzeptiert und eine Typkonvertierung durchführt. java.time hat nur Factory-Methoden, daher ist die Konvertierung ein Benutzerproblem, obwohl eine parse () -Methode für Zeichenketten bereitgestellt wird.
Es muss also eine statische Factory-Methode geben. Wenn wir die statischen Methoden durchsuchen, finden wir eine, die ziemlich ähnlich aussieht, aber nicht genau dieselbe ist.
Es hat 7 Int-Parameter wie unser ursprünglicher Joda-Time DateTime-Konstruktor. Wenn Sie jedoch nicht aufpassen, verpassen Sie ein wichtiges Detail. Der siebte Parameter steht nicht mehr für Millisekunden, er erwartet stattdessen Nanosekunden. Das liegt daran, dass java.time eine höhere Präzision als Joda-Time hat und Augenblicke auf die Nanosekunde genau misst. Ein wichtiges Detail, das Sie leicht übersehen haben könnten. Außerdem erwartet diese Methode eine ZoneID, sodass Sie sich fragen, warum Sie vorher keine benötigt haben und warum Sie sie jetzt benötigen.
Erinnern Sie sich an das Javadoc unseres ursprünglichen Konstruktors, in dem erwähnt wurde, dass er die Standardzeitzone verwenden würde. Vielleicht gibt es eine Möglichkeit, die Standard-ZoneId abzurufen?
Das javadoc für ZoneID sagt uns nichts über die aufgelisteten Konstruktoren, aber wenn wir uns die statischen Methoden ansehen, die wir sehen, können wir verwenden Systemstandard ()
Nachdem wir die ZoneID geklärt haben, was sollen wir mit unserer Konvertierung von Millisekunden in Nanosekunden tun? Vielleicht können wir java.util.concurrent.TimeUnit verwenden, um die Konvertierung durchzuführen.
Diese Methode gibt einen Long-Wert zurück und unsere Methode erwartet einen Int-Wert, sodass wir jetzt auch ein Konvertierungsproblem lösen müssen. Vielleicht könnten wir etwas Einfaches ausprobieren. Eine Multiplikation?
Das wird funktionieren, sieht aber etwas fehl am Platz aus. Falls Sie es noch nicht bemerkt haben, haben wir viel Zeit und Mühe aufgewendet, um eine einzelne Codezeile zu migrieren. Aber wie Sie sich vorstellen können, müssen wir viele solcher Änderungen von Hand vornehmen und es wird nicht besser.
Wenn wir uns jedoch die java.time-API etwas genauer ansehen, können wir eine Lösung finden, die etwas flüssiger aussieht.
Obwohl ZonedDateTime keine offensichtliche Möglichkeit hat, die Millisekunden festzulegen, kann dies mit dem mit der Methode (TemporalField field, long newValue), unter Verwendung Chronofield.Milli_of_Second wie das TemporalField.
Und das Java-Dokument erwähnt, dass es die Konvertierung in Nanosekunden für uns durchführen wird:
Wenn dieses Feld zum Einstellen eines Werts verwendet wird, sollte es sich genauso verhalten wie das Setzen von NANO_OF_SECOND, wobei der Wert mit 1.000.000 multipliziert wird.
Wir können also in der Factory-Methode einfach 0 für unsere Nanosekunden angeben und dann die mit Methode zum Erstellen einer ZonedDateTime, die alle Originalwerte sowie die Millisekunden enthält.
Wenn wir uns unser Endergebnis ansehen, sieht es so aus, als hätten wir nur eine einzige Codezeile geändert. Es zeigt nicht wirklich den Aufwand, der für die Recherche nur einer Migration aufgewendet wurde!
Erstellen Sie ein Rezept für eine schnellere und einfache Migration
Sensei bietet uns die Möglichkeit, diese hart erkämpften Informationen mit anderen Entwicklern zu teilen. Durch die Erstellung eines Rezepts, das all diese Anforderungen erfasst, können Sensei-Benutzer diese Migration mit einem Mausklick durchführen.
Ein Sensei-Rezept besteht aus 3 Hauptabschnitten:
- Metadaten
- Suche
- Verfügbare Problembehebungen
Schauen wir uns ein Sensei-Rezept an (kann auch als YAML-Rezept angesehen werden), das uns hilft, diesen Aufruf in sein java.time-Äquivalent zu migrieren.
DateTime foo = new DateTime (Jahr, Monat des Jahres, Tag des Monats, Stunde des Tages, Minute der Stunde, Sekunde der Minute, MillisofSekunde);
Abschnitt „Metadaten“
Der Metadatenbereich enthält Informationen über das Rezept und wie es verwendet werden sollte.
Abschnitt „Suchen“
Der Suchbereich eines Sensei-Rezepts gibt an, für welche Codeelemente dieses Rezept gelten soll.
suche:
Instanzerstellung:
Argumente:
1:
Typ: int
2:
Typ: int
3:
Typ: int
4:
Typ: int
5:
Typ: int
6:
Typ: int
7:
Typ: int
Anzahl Arg: 7
Typ: org.joda.time.DateTime
In diesem Suchbereich sehen wir, dass wir:
- Auf der Suche nach einem Instanzerstellung, d. h. die Verwendung eines Konstruktors. Hinweis: Es gibt viele andere Suchziele verfügbar
- Der Konstruktor sollte 7 Argumente haben, dies wird durch den ARG-Anzahl Eigentum
- Args 1-7 sollte vom Typ int sein
- Wir suchen Konstrukteure der Art org.joda.time.DateTime
Abschnitt „Verfügbare Korrekturen“
Im Abschnitt AvailableFixes können eine oder mehrere Korrekturen angegeben werden, die auf das entsprechende Codeelement angewendet werden können. Jeder Fix kann mehrere Aktionen haben, und in unserem Fall haben wir einen einzelnen Fix, der 2 Aktionen ausführt.
- Das Name Der Fix wird dem Benutzer im Menü „Quickfixes“ angezeigt und beschreibt, was passiert, wenn der Benutzer diesen Quickfix anwendet
- Die Aktionsliste zeigt, welche Aktionen von diesem Quickfix ausgeführt werden.
- Das umschreiben action schreibt das Codeelement mithilfe einer Schnurrbartvorlage neu. Es kann Variablen und Funktionen zum Ersetzen von Zeichenketten verwenden.
- Das Zugewiesene Variable ändern action prüft, ob dieser Konstruktor verwendet wird, um den Wert einer Variablen zuzuweisen. Wenn ja, ändert diese Aktion die Variable so, dass sie als der von angegebene Typ deklariert wird Art
Verwenden des Rezepts zur Codetransformation
Wenn 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 wir mit der Maus über den markierten Konstruktor fahren, werden uns die Optionen Recipe ShortDescription und Quickfix angezeigt Migrieren Sie zu java.time.ZonedDateTime

Nachdem wir die ausgewählt haben Migrieren Sie zu java.time.ZonedDateTime Quickfix, der Code wird gemäß den Aktionen transformiert, die wir im Rezept angegeben haben.

Eine einmalige Migration und teamübergreifende Codierungspraktiken — mit Sensei
In unserem obigen Beispiel können wir sehen, dass die Migration einer einzelnen Codezeile hart erkämpftes Wissen beinhalten kann. Sensei kann dieses Wissen in umsetzbare Rezepte oder Kochbücher umwandeln, die innerhalb von Teams geteilt werden können. Sie können einen einmaligen Migrations-Sprint planen oder den Ansatz verfolgen, schrittweise sofortige Transformationen an java.time durchzuführen, sobald Sie auf Joda-Time-Code stoßen. Sie können Rezepte aktivieren/deaktivieren, um Migrationen in logischen Phasen oder Schritten durchzuführen und sogar den Umfang der von Sensei gescannten Dateien zu erweitern oder zu reduzieren — 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. Du kannst immer nach Anti-Patterns oder bestimmten manuellen Codetransformationen Ausschau halten, auf die du bei Pull-Requests oder beim eigenen Programmieren häufig stößt. Wenn Sie eine Reihe von haben Richtlinien zur Codierung die von Entwicklern oft übersehen werden, dann könnten Sie die Richtlinien in Rezepte umwandeln, sodass Entwickler genehmigte Codetransformationen mit Zuversicht anwenden können.
Wenn Sie Fragen haben, würden wir uns freuen, von Ihnen zu hören! Besuchen Sie uns auf Slack unter: sensei-scw.slack.com
Govern AI-driven development before it ships
Measure AI-assisted risk, enforce secure coding policy at commit, and accelerate secure delivery across your SDLC.
Explore more blogs
Lorem ipsum diam quis enim lobortis scelerisque fermentum dui faucibus in ornare quam viverra orci sagittis eu volutpat odio facilisis.
%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

One Culture of Security: How Sage built their security champions program with agile secure code learning
Discover how Sage enhanced security with a flexible, relationship-focused approach, creating 200+ security champions and achieving measurable risk reduction.
.webp)
Why most CISOs are navigating AI adoption blindfolded (and how they can remove it)
Today, Secure Code Warrior issued an all-new white paper covering a prescriptive, directional AI adoption model that security leaders can use to identify their adoption stage and make real progress in bringing the AI security risks within their organization under control.
Secure AI-driven development before it ships
See developer risk, enforce policy, and prevent vulnerabilities across your software development lifecycle.

