Blog

Umstellung von Joda-Time auf java.time

Cameron Gregor
Veröffentlicht Nov 12, 2021

Die Migration von Code (sprich: Legacy-Code) ist kein Vergnügen. Es erfordert eine enorme Menge an Planung und Aufwand, um ihn über die Linie zu bringen. Es ist zwar nicht die aufregendste oder motivierendste Arbeit für Entwickler, aber es erfordert Entschlossenheit und die richtige Erfahrung, um Legacy-Code auf neue Bibliotheksversionen zu migrieren. 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 begonnen hat und Datums- und Zeitverarbeitung verwendet, dann hat es wahrscheinlich Joda-Time verwendet - eine ausgezeichnete Bibliothek und ein De-facto-Standard für die Handhabung von Datums- und Zeitfunktionen vor SE 8. Wenn Ihr Projekt immer noch Joda-Time verwendet, aber auf java.time migrieren möchte, dann lesen Sie weiter.

Mit der Veröffentlichung von Java SE 8 wurde eine neue und verbesserte Standard-API für Datum und Uhrzeit eingeführt, die gemeinhin als java.time (JSR-310) bezeichnet wird. Das Joda-Time-Projekt empfiehlt nun die Migration auf java.time (JSR-310).

Obwohl java.time (JSR-310) stark von Joda-Time inspiriert wurde, ist es nicht rückwärtskompatibel und Konzepte und Terminologien haben sich geändert. Deshalb erfordert die Migration von Joda-Time zu java.time eine sorgfältige Prüfung jeder einzelnen Codezeile, die Sie ändern. Dies kann zeitaufwändig sein und man würde sich fast wünschen, dass es einen einfacheren und automatisierten Weg zur Migration gäbe.

Es gibt einen besseren Weg zu migrieren, und wir haben ihn mit Sensei entwickelt - ein IntelliJ-Plugin, das automatisch Code-Transformationen nach den von Ihnen definierten Rezepten (Regeln) durchführt. Verbringen Sie Ihre Zeit damit, wiederverwendbare Rezepte zu definieren, anstatt sich wiederholende Migrationsaufgaben durchzuführen. Die Automatisierung wird nicht nur Ihren alten Joda-Time-Code transformieren, sondern auch den Teams helfen, 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 Standardization on java.time (JSR-310) erstellt, das Rezepte für die Migration von Joda-Time zu java.time auf eine weniger schmerzhafte Weise enthält. Dies ist ein wachsender Satz von Rezepten, den wir weiter ausbauen werden, um die Abdeckung mit weiteren Rezepten zu erhöhen.

Hier ist ein Beispiel für eine Migration, das Ihnen zeigt, wie Sensei die Migration von Legacy-Code vereinfacht.

Video zum Einstellen von java.time zoned date time

Von der sich wiederholenden manuellen Migration zu automatisierten Codeumwandlungen

Schauen wir uns ein Beispiel für die Erstellung einer neuen DateTime an, das ein paar versteckte Fallen bei der Migration einer einzigen Codezeile von Joda-Time zu java.time aufzeigt. Wir werden uns dann eines unserer Sensei Rezepte aus unserem Standardization on java.time (JSR-310) Kochbuch ansehen und zeigen, wie es all diese Informationen erfasst, so dass dieselbe Migration von jedem Entwickler wieder und wieder verwendet werden kann.

In diesem Beispiel konstruieren wir eine Joda-Time DateTime aus 7 int-Argumenten, die Werte der DateTime-Felder darstellen.

Wie können wir dies in ein java.time-Äquivalent migrieren?

Die Javadoc in Joda-Time für diesen Konstruktor sagt:

Konstruiert eine Instanz aus Datetime-Feldwerten unter Verwendung von ISOChronology in der Standardzeitzone.

Zunächst könnte man annehmen, dass es eine DateTime-Klasse in java.time gibt, aber das ist nicht der Fall. Wenn Sie nach "Migration von Joda-Time zu Java-Time" googeln, werden Sie höchstwahrscheinlich Stephen Colebournes Blogbeitrag Converting from Joda-Time to java.time finden.

Dies ist ein guter Anfang und weist uns den Weg zur Verwendung von java.time.ZonedDateTime oder java.time.OffsetDateTime. Hier stellt sich die erste Frage: Welche soll ich verwenden? Wahrscheinlich ZonedDateTime, basierend auf Stephens Kommentaren.

Wenn wir im Javadoc von ZonedDateTime nachsehen, können wir überhaupt keine Konstruktoren finden. Wir kehren zu Stephens Blogbeitrag zurück und lesen weiter unten:

Konstruktion. Joda-Time hat einen Konstruktor, der ein Objekt akzeptiert und eine Typkonvertierung durchführt. java.time hat nur Factory-Methoden, so dass die Konvertierung ein Benutzerproblem ist, obwohl eine parse()-Methode für Strings zur Verfügung steht.

Es muss also eine statische Fabrikmethode geben, und beim Durchsuchen der statischen Methoden finden wir eine, die ziemlich ähnlich aussieht, aber nicht genau dieselbe ist.

Er hat 7 int-Parameter wie unser ursprünglicher Joda-Time DateTime-Konstruktor, aber wenn Sie nicht aufpassen, werden Sie ein wichtiges Detail übersehen. Der 7. Parameter steht nicht mehr für Millisekunden, sondern für Nanosekunden. Das liegt daran, dass java.time die Genauigkeit gegenüber Joda-Time erhöht hat und Instanten auf die Nanosekunde genau misst. Ein wichtiges Detail, das Sie leicht hätten übersehen können. Außerdem erwartet diese Methode eine ZoneId, so dass man sich fragt, warum man vorher keine brauchte und warum man sie jetzt braucht.

Erinnern Sie sich an die Javadoc unserer ursprünglichen Konstruktor, die es würde die Standard-Zeitzone verwenden erwähnt, vielleicht gibt es eine Möglichkeit, die Standard-ZoneId zu erhalten?

In der Javadoc für ZoneId sind keine Konstruktoren aufgeführt, aber wenn wir uns die statischen Methoden ansehen, sehen wir, dass wir systemDefault()verwenden können

Nun, da wir die ZoneId geklärt haben, was sollen wir mit der Konvertierung von Millisekunden in NanoSekunden tun? Vielleicht können wir java.util.concurrent.TimeUnit verwenden, um die Umwandlung durchzuführen.

Diese Methode gibt einen long zurück, und unsere Methode erwartet einen int, so dass wir jetzt auch ein Konvertierungsproblem zu lösen haben. Vielleicht können wir etwas Einfaches versuchen. Eine Multiplikation?

Das funktioniert zwar, sieht aber ein wenig deplatziert aus. Falls Sie es noch nicht bemerkt haben: Wir haben viel Zeit und Mühe investiert, um eine einzige Codezeile zu migrieren. Aber wie Sie sich vorstellen können, müssen wir viele solcher Bearbeitungen 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 entdecken, die etwas flüssiger aussieht.

Obwohl ZonedDateTime keine offensichtliche Möglichkeit bietet, die Millisekunden zu setzen, kann dies mit der Methode with(TemporalField field, long newValue) erfolgen, wobei ChronoField.MILLI_OF_SECOND als TemporalField verwendet wird.

Und in der Java-Doku wird erwähnt, dass es die Konvertierung in Nanosekunden für uns durchführt:

Wenn dieses Feld zur Einstellung eines Wertes verwendet wird, sollte es sich genauso verhalten wie die Einstellung von NANO_OF_SECOND, wobei der Wert mit 1.000.000 multipliziert wird.

Wir können also einfach 0 für unsere Nanosekunden in der Factory-Methode angeben und dann die With-Methode verwenden, um eine ZonedDateTime zu erstellen, die alle ursprünglichen Werte sowie die Millisekunden enthält.

Wenn man sich unser Endergebnis ansieht, sieht es so aus, als hätten wir nur eine einzige Codezeile geändert. Das zeigt nicht wirklich den Aufwand, der mit der Erforschung einer einzigen Migration verbunden war!

Erstellen Sie ein Rezept, um schneller und einfacher zu migrieren

Sensei bietet uns die Möglichkeit, diese hart erarbeiteten Informationen mit anderen Entwicklern zu teilen. Durch die Erstellung eines Rezepts, in dem all diese Anforderungen erfasst sind, können die Benutzer von Sensei diese Migration mit einem Mausklick durchführen.

Ein Sensei Rezept besteht aus 3 Hauptteilen:

  • Metadaten
  • Suche
  • AvailableFixes

Schauen wir uns ein Sensei Rezept an (kann auch als YAML-Rezept betrachtet werden), das uns hilft, diesen Aufruf in sein java.time-Äquivalent zu migrieren.

DateTime foo = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond);

Abschnitt Metadaten

Der Abschnitt Metadaten enthält Informationen über das Rezept und seine Verwendung.

Bereich Suche

Der Suchabschnitt eines Sensei Rezepts gibt an, auf welche Code-Elemente dieses 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 Suchabschnitt sehen wir, dass wir es sind:

  • Suche nach einer instanceCreation, d.h. einer Verwendung eines Constructors. Hinweis: Es sind viele andere Suchziele verfügbar
  • Der Konstruktor sollte 7 Argumente haben, dies wird durch die Eigenschaft argCount angegeben
  • args 1-7 sollten vom Typ int sein
  • Wir suchen nach Konstruktoren vom Typ 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. Jede Korrektur kann mehrere Aktionen haben, und in unserem Fall haben wir eine einzige Korrektur, die 2 Aktionen ausführt.

  • Der Name des Fixes wird dem Benutzer im Menü "Quickfixes" angezeigt und beschreibt, was passiert, wenn der Benutzer diesen Quickfix anwendet
  • Die Liste der Aktionen zeigt, welche Aktionen durch diesen Quickfix ausgeführt werden
  • Die Rewrite-Aktion schreibt das Code-Element unter Verwendung einer Mustache-Vorlage um. Dabei können Variablen und Funktionen zur Ersetzung von Zeichenketten verwendet werden.
  • Die Aktion modifyAssignedVariable prüft, ob dieser Konstruktor verwendet wird, um einer Variablen einen Wert zuzuweisen. Wenn dies der Fall ist, ändert diese Aktion die Variable so, dass sie als der Typ deklariert wird, der durch type

Verwendung des Rezepts für die Codeumwandlung

Wenn unser Rezept geschrieben und aktiviert ist, scannt es unseren Code und markiert die Segmente, auf die es angewendet werden kann.

Im folgenden Screenshot sehen wir, dass der Zielkonstruktor mit Sensei markiert wurde. Wenn wir den Mauszeiger über den markierten Konstruktor bewegen, sehen wir die Recipe shortDescription und die Quickfix-Option Migrate to java.time.ZonedDateTime

Migrieren Neues Datum Uhrzeit

Nachdem wir den Quickfix Migrate to java.time.ZonedDateTime ausgewählt haben, wird der Code entsprechend den im Rezept angegebenen Aktionen umgewandelt.

Zonen Datum Uhrzeit mit Jahr Monat Tag Stunde

Eine einmalige Migration und einheitliche Kodierungspraktiken in allen Teams - mit Sensei

Wie wir an unserem obigen Beispiel sehen, kann die Migration einer einzigen Codezeile hart erarbeitetes Wissen beinhalten. 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, inkrementelle, sofortige Transformationen zu 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 Migration von Bibliotheken ist nur ein Beispiel für die vielen Möglichkeiten, die Sensei bietet, um Ihre Projekte zu standardisieren. Sie können immer nach Anti-Patterns oder bestimmten manuellen Code-Transformationen Ausschau halten, auf die Sie häufig in Pull-Requests oder beim Coding selbst stoßen. Wenn Sie über eine Reihe von Codierungsrichtlinien verfügen, die von den Entwicklern häufig übersehen werden, können Sie diese Richtlinien in Rezepte umwandeln, so dass die Entwickler bewährte Codeumwandlungen sicher anwenden können.

Wenn Sie Fragen haben, würden wir uns freuen, von Ihnen zu hören! Treten Sie uns auf Slack bei: sensei-scw.slack.com

Ressource anzeigen
Ressource anzeigen

Migrieren Sie Joda-Time nach java.time auf bequeme Weise

Interessiert an mehr?

Cameron ist ein leitender Softwareentwickler bei Secure Code Warrior. Er verfügt über mehr als 15 Jahre Erfahrung in der Bereitstellung von Software. Er setzt sich leidenschaftlich für die Produktivität von Entwicklern ein und trägt aktiv zu Open-Source-Software bei.

Secure Code Warrior ist für Ihr Unternehmen da, um Sie dabei zu unterstützen, Ihren Code über den gesamten Lebenszyklus der Softwareentwicklung hinweg zu sichern und eine Kultur zu schaffen, in der Cybersicherheit an erster Stelle steht. Ganz gleich, ob Sie AppSec-Manager, Entwickler, CISO oder ein anderer Sicherheitsverantwortlicher sind, wir können Ihrem Unternehmen helfen, die mit unsicherem Code verbundenen Risiken zu reduzieren.

Demo buchen
Weitergeben:
Autor
Cameron Gregor
Veröffentlicht Nov 12, 2021

Cameron ist ein leitender Softwareentwickler bei Secure Code Warrior. Er verfügt über mehr als 15 Jahre Erfahrung in der Bereitstellung von Software. Er setzt sich leidenschaftlich für die Produktivität von Entwicklern ein und trägt aktiv zu Open-Source-Software bei.

Weitergeben:

Die Migration von Code (sprich: Legacy-Code) ist kein Vergnügen. Es erfordert eine enorme Menge an Planung und Aufwand, um ihn über die Linie zu bringen. Es ist zwar nicht die aufregendste oder motivierendste Arbeit für Entwickler, aber es erfordert Entschlossenheit und die richtige Erfahrung, um Legacy-Code auf neue Bibliotheksversionen zu migrieren. 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 begonnen hat und Datums- und Zeitverarbeitung verwendet, dann hat es wahrscheinlich Joda-Time verwendet - eine ausgezeichnete Bibliothek und ein De-facto-Standard für die Handhabung von Datums- und Zeitfunktionen vor SE 8. Wenn Ihr Projekt immer noch Joda-Time verwendet, aber auf java.time migrieren möchte, dann lesen Sie weiter.

Mit der Veröffentlichung von Java SE 8 wurde eine neue und verbesserte Standard-API für Datum und Uhrzeit eingeführt, die gemeinhin als java.time (JSR-310) bezeichnet wird. Das Joda-Time-Projekt empfiehlt nun die Migration auf java.time (JSR-310).

Obwohl java.time (JSR-310) stark von Joda-Time inspiriert wurde, ist es nicht rückwärtskompatibel und Konzepte und Terminologien haben sich geändert. Deshalb erfordert die Migration von Joda-Time zu java.time eine sorgfältige Prüfung jeder einzelnen Codezeile, die Sie ändern. Dies kann zeitaufwändig sein und man würde sich fast wünschen, dass es einen einfacheren und automatisierten Weg zur Migration gäbe.

Es gibt einen besseren Weg zu migrieren, und wir haben ihn mit Sensei entwickelt - ein IntelliJ-Plugin, das automatisch Code-Transformationen nach den von Ihnen definierten Rezepten (Regeln) durchführt. Verbringen Sie Ihre Zeit damit, wiederverwendbare Rezepte zu definieren, anstatt sich wiederholende Migrationsaufgaben durchzuführen. Die Automatisierung wird nicht nur Ihren alten Joda-Time-Code transformieren, sondern auch den Teams helfen, 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 Standardization on java.time (JSR-310) erstellt, das Rezepte für die Migration von Joda-Time zu java.time auf eine weniger schmerzhafte Weise enthält. Dies ist ein wachsender Satz von Rezepten, den wir weiter ausbauen werden, um die Abdeckung mit weiteren Rezepten zu erhöhen.

Hier ist ein Beispiel für eine Migration, das Ihnen zeigt, wie Sensei die Migration von Legacy-Code vereinfacht.

Video zum Einstellen von java.time zoned date time

Von der sich wiederholenden manuellen Migration zu automatisierten Codeumwandlungen

Schauen wir uns ein Beispiel für die Erstellung einer neuen DateTime an, das ein paar versteckte Fallen bei der Migration einer einzigen Codezeile von Joda-Time zu java.time aufzeigt. Wir werden uns dann eines unserer Sensei Rezepte aus unserem Standardization on java.time (JSR-310) Kochbuch ansehen und zeigen, wie es all diese Informationen erfasst, so dass dieselbe Migration von jedem Entwickler wieder und wieder verwendet werden kann.

In diesem Beispiel konstruieren wir eine Joda-Time DateTime aus 7 int-Argumenten, die Werte der DateTime-Felder darstellen.

Wie können wir dies in ein java.time-Äquivalent migrieren?

Die Javadoc in Joda-Time für diesen Konstruktor sagt:

Konstruiert eine Instanz aus Datetime-Feldwerten unter Verwendung von ISOChronology in der Standardzeitzone.

Zunächst könnte man annehmen, dass es eine DateTime-Klasse in java.time gibt, aber das ist nicht der Fall. Wenn Sie nach "Migration von Joda-Time zu Java-Time" googeln, werden Sie höchstwahrscheinlich Stephen Colebournes Blogbeitrag Converting from Joda-Time to java.time finden.

Dies ist ein guter Anfang und weist uns den Weg zur Verwendung von java.time.ZonedDateTime oder java.time.OffsetDateTime. Hier stellt sich die erste Frage: Welche soll ich verwenden? Wahrscheinlich ZonedDateTime, basierend auf Stephens Kommentaren.

Wenn wir im Javadoc von ZonedDateTime nachsehen, können wir überhaupt keine Konstruktoren finden. Wir kehren zu Stephens Blogbeitrag zurück und lesen weiter unten:

Konstruktion. Joda-Time hat einen Konstruktor, der ein Objekt akzeptiert und eine Typkonvertierung durchführt. java.time hat nur Factory-Methoden, so dass die Konvertierung ein Benutzerproblem ist, obwohl eine parse()-Methode für Strings zur Verfügung steht.

Es muss also eine statische Fabrikmethode geben, und beim Durchsuchen der statischen Methoden finden wir eine, die ziemlich ähnlich aussieht, aber nicht genau dieselbe ist.

Er hat 7 int-Parameter wie unser ursprünglicher Joda-Time DateTime-Konstruktor, aber wenn Sie nicht aufpassen, werden Sie ein wichtiges Detail übersehen. Der 7. Parameter steht nicht mehr für Millisekunden, sondern für Nanosekunden. Das liegt daran, dass java.time die Genauigkeit gegenüber Joda-Time erhöht hat und Instanten auf die Nanosekunde genau misst. Ein wichtiges Detail, das Sie leicht hätten übersehen können. Außerdem erwartet diese Methode eine ZoneId, so dass man sich fragt, warum man vorher keine brauchte und warum man sie jetzt braucht.

Erinnern Sie sich an die Javadoc unserer ursprünglichen Konstruktor, die es würde die Standard-Zeitzone verwenden erwähnt, vielleicht gibt es eine Möglichkeit, die Standard-ZoneId zu erhalten?

In der Javadoc für ZoneId sind keine Konstruktoren aufgeführt, aber wenn wir uns die statischen Methoden ansehen, sehen wir, dass wir systemDefault()verwenden können

Nun, da wir die ZoneId geklärt haben, was sollen wir mit der Konvertierung von Millisekunden in NanoSekunden tun? Vielleicht können wir java.util.concurrent.TimeUnit verwenden, um die Umwandlung durchzuführen.

Diese Methode gibt einen long zurück, und unsere Methode erwartet einen int, so dass wir jetzt auch ein Konvertierungsproblem zu lösen haben. Vielleicht können wir etwas Einfaches versuchen. Eine Multiplikation?

Das funktioniert zwar, sieht aber ein wenig deplatziert aus. Falls Sie es noch nicht bemerkt haben: Wir haben viel Zeit und Mühe investiert, um eine einzige Codezeile zu migrieren. Aber wie Sie sich vorstellen können, müssen wir viele solcher Bearbeitungen 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 entdecken, die etwas flüssiger aussieht.

Obwohl ZonedDateTime keine offensichtliche Möglichkeit bietet, die Millisekunden zu setzen, kann dies mit der Methode with(TemporalField field, long newValue) erfolgen, wobei ChronoField.MILLI_OF_SECOND als TemporalField verwendet wird.

Und in der Java-Doku wird erwähnt, dass es die Konvertierung in Nanosekunden für uns durchführt:

Wenn dieses Feld zur Einstellung eines Wertes verwendet wird, sollte es sich genauso verhalten wie die Einstellung von NANO_OF_SECOND, wobei der Wert mit 1.000.000 multipliziert wird.

Wir können also einfach 0 für unsere Nanosekunden in der Factory-Methode angeben und dann die With-Methode verwenden, um eine ZonedDateTime zu erstellen, die alle ursprünglichen Werte sowie die Millisekunden enthält.

Wenn man sich unser Endergebnis ansieht, sieht es so aus, als hätten wir nur eine einzige Codezeile geändert. Das zeigt nicht wirklich den Aufwand, der mit der Erforschung einer einzigen Migration verbunden war!

Erstellen Sie ein Rezept, um schneller und einfacher zu migrieren

Sensei bietet uns die Möglichkeit, diese hart erarbeiteten Informationen mit anderen Entwicklern zu teilen. Durch die Erstellung eines Rezepts, in dem all diese Anforderungen erfasst sind, können die Benutzer von Sensei diese Migration mit einem Mausklick durchführen.

Ein Sensei Rezept besteht aus 3 Hauptteilen:

  • Metadaten
  • Suche
  • AvailableFixes

Schauen wir uns ein Sensei Rezept an (kann auch als YAML-Rezept betrachtet werden), das uns hilft, diesen Aufruf in sein java.time-Äquivalent zu migrieren.

DateTime foo = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond);

Abschnitt Metadaten

Der Abschnitt Metadaten enthält Informationen über das Rezept und seine Verwendung.

Bereich Suche

Der Suchabschnitt eines Sensei Rezepts gibt an, auf welche Code-Elemente dieses 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 Suchabschnitt sehen wir, dass wir es sind:

  • Suche nach einer instanceCreation, d.h. einer Verwendung eines Constructors. Hinweis: Es sind viele andere Suchziele verfügbar
  • Der Konstruktor sollte 7 Argumente haben, dies wird durch die Eigenschaft argCount angegeben
  • args 1-7 sollten vom Typ int sein
  • Wir suchen nach Konstruktoren vom Typ 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. Jede Korrektur kann mehrere Aktionen haben, und in unserem Fall haben wir eine einzige Korrektur, die 2 Aktionen ausführt.

  • Der Name des Fixes wird dem Benutzer im Menü "Quickfixes" angezeigt und beschreibt, was passiert, wenn der Benutzer diesen Quickfix anwendet
  • Die Liste der Aktionen zeigt, welche Aktionen durch diesen Quickfix ausgeführt werden
  • Die Rewrite-Aktion schreibt das Code-Element unter Verwendung einer Mustache-Vorlage um. Dabei können Variablen und Funktionen zur Ersetzung von Zeichenketten verwendet werden.
  • Die Aktion modifyAssignedVariable prüft, ob dieser Konstruktor verwendet wird, um einer Variablen einen Wert zuzuweisen. Wenn dies der Fall ist, ändert diese Aktion die Variable so, dass sie als der Typ deklariert wird, der durch type

Verwendung des Rezepts für die Codeumwandlung

Wenn unser Rezept geschrieben und aktiviert ist, scannt es unseren Code und markiert die Segmente, auf die es angewendet werden kann.

Im folgenden Screenshot sehen wir, dass der Zielkonstruktor mit Sensei markiert wurde. Wenn wir den Mauszeiger über den markierten Konstruktor bewegen, sehen wir die Recipe shortDescription und die Quickfix-Option Migrate to java.time.ZonedDateTime

Migrieren Neues Datum Uhrzeit

Nachdem wir den Quickfix Migrate to java.time.ZonedDateTime ausgewählt haben, wird der Code entsprechend den im Rezept angegebenen Aktionen umgewandelt.

Zonen Datum Uhrzeit mit Jahr Monat Tag Stunde

Eine einmalige Migration und einheitliche Kodierungspraktiken in allen Teams - mit Sensei

Wie wir an unserem obigen Beispiel sehen, kann die Migration einer einzigen Codezeile hart erarbeitetes Wissen beinhalten. 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, inkrementelle, sofortige Transformationen zu 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 Migration von Bibliotheken ist nur ein Beispiel für die vielen Möglichkeiten, die Sensei bietet, um Ihre Projekte zu standardisieren. Sie können immer nach Anti-Patterns oder bestimmten manuellen Code-Transformationen Ausschau halten, auf die Sie häufig in Pull-Requests oder beim Coding selbst stoßen. Wenn Sie über eine Reihe von Codierungsrichtlinien verfügen, die von den Entwicklern häufig übersehen werden, können Sie diese Richtlinien in Rezepte umwandeln, so dass die Entwickler bewährte Codeumwandlungen sicher anwenden können.

Wenn Sie Fragen haben, würden wir uns freuen, von Ihnen zu hören! Treten Sie uns auf Slack bei: sensei-scw.slack.com

Ressource anzeigen
Ressource anzeigen

Füllen Sie das folgende Formular aus, um den Bericht herunterzuladen

Wir bitten Sie um Ihre Erlaubnis, Ihnen Informationen über unsere Produkte und/oder verwandte Themen der sicheren Codierung zuzusenden. Wir werden Ihre persönlichen Daten immer mit äußerster Sorgfalt behandeln und sie niemals zu Marketingzwecken an andere Unternehmen verkaufen.

Senden
Um das Formular abzuschicken, aktivieren Sie bitte "Analytics"-Cookies. Sie können die Cookies wieder deaktivieren, sobald Sie fertig sind.

Die Migration von Code (sprich: Legacy-Code) ist kein Vergnügen. Es erfordert eine enorme Menge an Planung und Aufwand, um ihn über die Linie zu bringen. Es ist zwar nicht die aufregendste oder motivierendste Arbeit für Entwickler, aber es erfordert Entschlossenheit und die richtige Erfahrung, um Legacy-Code auf neue Bibliotheksversionen zu migrieren. 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 begonnen hat und Datums- und Zeitverarbeitung verwendet, dann hat es wahrscheinlich Joda-Time verwendet - eine ausgezeichnete Bibliothek und ein De-facto-Standard für die Handhabung von Datums- und Zeitfunktionen vor SE 8. Wenn Ihr Projekt immer noch Joda-Time verwendet, aber auf java.time migrieren möchte, dann lesen Sie weiter.

Mit der Veröffentlichung von Java SE 8 wurde eine neue und verbesserte Standard-API für Datum und Uhrzeit eingeführt, die gemeinhin als java.time (JSR-310) bezeichnet wird. Das Joda-Time-Projekt empfiehlt nun die Migration auf java.time (JSR-310).

Obwohl java.time (JSR-310) stark von Joda-Time inspiriert wurde, ist es nicht rückwärtskompatibel und Konzepte und Terminologien haben sich geändert. Deshalb erfordert die Migration von Joda-Time zu java.time eine sorgfältige Prüfung jeder einzelnen Codezeile, die Sie ändern. Dies kann zeitaufwändig sein und man würde sich fast wünschen, dass es einen einfacheren und automatisierten Weg zur Migration gäbe.

Es gibt einen besseren Weg zu migrieren, und wir haben ihn mit Sensei entwickelt - ein IntelliJ-Plugin, das automatisch Code-Transformationen nach den von Ihnen definierten Rezepten (Regeln) durchführt. Verbringen Sie Ihre Zeit damit, wiederverwendbare Rezepte zu definieren, anstatt sich wiederholende Migrationsaufgaben durchzuführen. Die Automatisierung wird nicht nur Ihren alten Joda-Time-Code transformieren, sondern auch den Teams helfen, 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 Standardization on java.time (JSR-310) erstellt, das Rezepte für die Migration von Joda-Time zu java.time auf eine weniger schmerzhafte Weise enthält. Dies ist ein wachsender Satz von Rezepten, den wir weiter ausbauen werden, um die Abdeckung mit weiteren Rezepten zu erhöhen.

Hier ist ein Beispiel für eine Migration, das Ihnen zeigt, wie Sensei die Migration von Legacy-Code vereinfacht.

Video zum Einstellen von java.time zoned date time

Von der sich wiederholenden manuellen Migration zu automatisierten Codeumwandlungen

Schauen wir uns ein Beispiel für die Erstellung einer neuen DateTime an, das ein paar versteckte Fallen bei der Migration einer einzigen Codezeile von Joda-Time zu java.time aufzeigt. Wir werden uns dann eines unserer Sensei Rezepte aus unserem Standardization on java.time (JSR-310) Kochbuch ansehen und zeigen, wie es all diese Informationen erfasst, so dass dieselbe Migration von jedem Entwickler wieder und wieder verwendet werden kann.

In diesem Beispiel konstruieren wir eine Joda-Time DateTime aus 7 int-Argumenten, die Werte der DateTime-Felder darstellen.

Wie können wir dies in ein java.time-Äquivalent migrieren?

Die Javadoc in Joda-Time für diesen Konstruktor sagt:

Konstruiert eine Instanz aus Datetime-Feldwerten unter Verwendung von ISOChronology in der Standardzeitzone.

Zunächst könnte man annehmen, dass es eine DateTime-Klasse in java.time gibt, aber das ist nicht der Fall. Wenn Sie nach "Migration von Joda-Time zu Java-Time" googeln, werden Sie höchstwahrscheinlich Stephen Colebournes Blogbeitrag Converting from Joda-Time to java.time finden.

Dies ist ein guter Anfang und weist uns den Weg zur Verwendung von java.time.ZonedDateTime oder java.time.OffsetDateTime. Hier stellt sich die erste Frage: Welche soll ich verwenden? Wahrscheinlich ZonedDateTime, basierend auf Stephens Kommentaren.

Wenn wir im Javadoc von ZonedDateTime nachsehen, können wir überhaupt keine Konstruktoren finden. Wir kehren zu Stephens Blogbeitrag zurück und lesen weiter unten:

Konstruktion. Joda-Time hat einen Konstruktor, der ein Objekt akzeptiert und eine Typkonvertierung durchführt. java.time hat nur Factory-Methoden, so dass die Konvertierung ein Benutzerproblem ist, obwohl eine parse()-Methode für Strings zur Verfügung steht.

Es muss also eine statische Fabrikmethode geben, und beim Durchsuchen der statischen Methoden finden wir eine, die ziemlich ähnlich aussieht, aber nicht genau dieselbe ist.

Er hat 7 int-Parameter wie unser ursprünglicher Joda-Time DateTime-Konstruktor, aber wenn Sie nicht aufpassen, werden Sie ein wichtiges Detail übersehen. Der 7. Parameter steht nicht mehr für Millisekunden, sondern für Nanosekunden. Das liegt daran, dass java.time die Genauigkeit gegenüber Joda-Time erhöht hat und Instanten auf die Nanosekunde genau misst. Ein wichtiges Detail, das Sie leicht hätten übersehen können. Außerdem erwartet diese Methode eine ZoneId, so dass man sich fragt, warum man vorher keine brauchte und warum man sie jetzt braucht.

Erinnern Sie sich an die Javadoc unserer ursprünglichen Konstruktor, die es würde die Standard-Zeitzone verwenden erwähnt, vielleicht gibt es eine Möglichkeit, die Standard-ZoneId zu erhalten?

In der Javadoc für ZoneId sind keine Konstruktoren aufgeführt, aber wenn wir uns die statischen Methoden ansehen, sehen wir, dass wir systemDefault()verwenden können

Nun, da wir die ZoneId geklärt haben, was sollen wir mit der Konvertierung von Millisekunden in NanoSekunden tun? Vielleicht können wir java.util.concurrent.TimeUnit verwenden, um die Umwandlung durchzuführen.

Diese Methode gibt einen long zurück, und unsere Methode erwartet einen int, so dass wir jetzt auch ein Konvertierungsproblem zu lösen haben. Vielleicht können wir etwas Einfaches versuchen. Eine Multiplikation?

Das funktioniert zwar, sieht aber ein wenig deplatziert aus. Falls Sie es noch nicht bemerkt haben: Wir haben viel Zeit und Mühe investiert, um eine einzige Codezeile zu migrieren. Aber wie Sie sich vorstellen können, müssen wir viele solcher Bearbeitungen 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 entdecken, die etwas flüssiger aussieht.

Obwohl ZonedDateTime keine offensichtliche Möglichkeit bietet, die Millisekunden zu setzen, kann dies mit der Methode with(TemporalField field, long newValue) erfolgen, wobei ChronoField.MILLI_OF_SECOND als TemporalField verwendet wird.

Und in der Java-Doku wird erwähnt, dass es die Konvertierung in Nanosekunden für uns durchführt:

Wenn dieses Feld zur Einstellung eines Wertes verwendet wird, sollte es sich genauso verhalten wie die Einstellung von NANO_OF_SECOND, wobei der Wert mit 1.000.000 multipliziert wird.

Wir können also einfach 0 für unsere Nanosekunden in der Factory-Methode angeben und dann die With-Methode verwenden, um eine ZonedDateTime zu erstellen, die alle ursprünglichen Werte sowie die Millisekunden enthält.

Wenn man sich unser Endergebnis ansieht, sieht es so aus, als hätten wir nur eine einzige Codezeile geändert. Das zeigt nicht wirklich den Aufwand, der mit der Erforschung einer einzigen Migration verbunden war!

Erstellen Sie ein Rezept, um schneller und einfacher zu migrieren

Sensei bietet uns die Möglichkeit, diese hart erarbeiteten Informationen mit anderen Entwicklern zu teilen. Durch die Erstellung eines Rezepts, in dem all diese Anforderungen erfasst sind, können die Benutzer von Sensei diese Migration mit einem Mausklick durchführen.

Ein Sensei Rezept besteht aus 3 Hauptteilen:

  • Metadaten
  • Suche
  • AvailableFixes

Schauen wir uns ein Sensei Rezept an (kann auch als YAML-Rezept betrachtet werden), das uns hilft, diesen Aufruf in sein java.time-Äquivalent zu migrieren.

DateTime foo = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond);

Abschnitt Metadaten

Der Abschnitt Metadaten enthält Informationen über das Rezept und seine Verwendung.

Bereich Suche

Der Suchabschnitt eines Sensei Rezepts gibt an, auf welche Code-Elemente dieses 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 Suchabschnitt sehen wir, dass wir es sind:

  • Suche nach einer instanceCreation, d.h. einer Verwendung eines Constructors. Hinweis: Es sind viele andere Suchziele verfügbar
  • Der Konstruktor sollte 7 Argumente haben, dies wird durch die Eigenschaft argCount angegeben
  • args 1-7 sollten vom Typ int sein
  • Wir suchen nach Konstruktoren vom Typ 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. Jede Korrektur kann mehrere Aktionen haben, und in unserem Fall haben wir eine einzige Korrektur, die 2 Aktionen ausführt.

  • Der Name des Fixes wird dem Benutzer im Menü "Quickfixes" angezeigt und beschreibt, was passiert, wenn der Benutzer diesen Quickfix anwendet
  • Die Liste der Aktionen zeigt, welche Aktionen durch diesen Quickfix ausgeführt werden
  • Die Rewrite-Aktion schreibt das Code-Element unter Verwendung einer Mustache-Vorlage um. Dabei können Variablen und Funktionen zur Ersetzung von Zeichenketten verwendet werden.
  • Die Aktion modifyAssignedVariable prüft, ob dieser Konstruktor verwendet wird, um einer Variablen einen Wert zuzuweisen. Wenn dies der Fall ist, ändert diese Aktion die Variable so, dass sie als der Typ deklariert wird, der durch type

Verwendung des Rezepts für die Codeumwandlung

Wenn unser Rezept geschrieben und aktiviert ist, scannt es unseren Code und markiert die Segmente, auf die es angewendet werden kann.

Im folgenden Screenshot sehen wir, dass der Zielkonstruktor mit Sensei markiert wurde. Wenn wir den Mauszeiger über den markierten Konstruktor bewegen, sehen wir die Recipe shortDescription und die Quickfix-Option Migrate to java.time.ZonedDateTime

Migrieren Neues Datum Uhrzeit

Nachdem wir den Quickfix Migrate to java.time.ZonedDateTime ausgewählt haben, wird der Code entsprechend den im Rezept angegebenen Aktionen umgewandelt.

Zonen Datum Uhrzeit mit Jahr Monat Tag Stunde

Eine einmalige Migration und einheitliche Kodierungspraktiken in allen Teams - mit Sensei

Wie wir an unserem obigen Beispiel sehen, kann die Migration einer einzigen Codezeile hart erarbeitetes Wissen beinhalten. 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, inkrementelle, sofortige Transformationen zu 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 Migration von Bibliotheken ist nur ein Beispiel für die vielen Möglichkeiten, die Sensei bietet, um Ihre Projekte zu standardisieren. Sie können immer nach Anti-Patterns oder bestimmten manuellen Code-Transformationen Ausschau halten, auf die Sie häufig in Pull-Requests oder beim Coding selbst stoßen. Wenn Sie über eine Reihe von Codierungsrichtlinien verfügen, die von den Entwicklern häufig übersehen werden, können Sie diese Richtlinien in Rezepte umwandeln, so dass die Entwickler bewährte Codeumwandlungen sicher anwenden können.

Wenn Sie Fragen haben, würden wir uns freuen, von Ihnen zu hören! Treten Sie uns auf Slack bei: sensei-scw.slack.com

Auf Ressource zugreifen

Klicken Sie auf den unten stehenden Link und laden Sie die PDF-Datei dieser Ressource herunter.

Secure Code Warrior ist für Ihr Unternehmen da, um Sie dabei zu unterstützen, Ihren Code über den gesamten Lebenszyklus der Softwareentwicklung hinweg zu sichern und eine Kultur zu schaffen, in der Cybersicherheit an erster Stelle steht. Ganz gleich, ob Sie AppSec-Manager, Entwickler, CISO oder ein anderer Sicherheitsverantwortlicher sind, wir können Ihrem Unternehmen helfen, die mit unsicherem Code verbundenen Risiken zu reduzieren.

Bericht ansehenDemo buchen
PDF herunterladen
Ressource anzeigen
Weitergeben:
Interessiert an mehr?

Weitergeben:
Autor
Cameron Gregor
Veröffentlicht Nov 12, 2021

Cameron ist ein leitender Softwareentwickler bei Secure Code Warrior. Er verfügt über mehr als 15 Jahre Erfahrung in der Bereitstellung von Software. Er setzt sich leidenschaftlich für die Produktivität von Entwicklern ein und trägt aktiv zu Open-Source-Software bei.

Weitergeben:

Die Migration von Code (sprich: Legacy-Code) ist kein Vergnügen. Es erfordert eine enorme Menge an Planung und Aufwand, um ihn über die Linie zu bringen. Es ist zwar nicht die aufregendste oder motivierendste Arbeit für Entwickler, aber es erfordert Entschlossenheit und die richtige Erfahrung, um Legacy-Code auf neue Bibliotheksversionen zu migrieren. 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 begonnen hat und Datums- und Zeitverarbeitung verwendet, dann hat es wahrscheinlich Joda-Time verwendet - eine ausgezeichnete Bibliothek und ein De-facto-Standard für die Handhabung von Datums- und Zeitfunktionen vor SE 8. Wenn Ihr Projekt immer noch Joda-Time verwendet, aber auf java.time migrieren möchte, dann lesen Sie weiter.

Mit der Veröffentlichung von Java SE 8 wurde eine neue und verbesserte Standard-API für Datum und Uhrzeit eingeführt, die gemeinhin als java.time (JSR-310) bezeichnet wird. Das Joda-Time-Projekt empfiehlt nun die Migration auf java.time (JSR-310).

Obwohl java.time (JSR-310) stark von Joda-Time inspiriert wurde, ist es nicht rückwärtskompatibel und Konzepte und Terminologien haben sich geändert. Deshalb erfordert die Migration von Joda-Time zu java.time eine sorgfältige Prüfung jeder einzelnen Codezeile, die Sie ändern. Dies kann zeitaufwändig sein und man würde sich fast wünschen, dass es einen einfacheren und automatisierten Weg zur Migration gäbe.

Es gibt einen besseren Weg zu migrieren, und wir haben ihn mit Sensei entwickelt - ein IntelliJ-Plugin, das automatisch Code-Transformationen nach den von Ihnen definierten Rezepten (Regeln) durchführt. Verbringen Sie Ihre Zeit damit, wiederverwendbare Rezepte zu definieren, anstatt sich wiederholende Migrationsaufgaben durchzuführen. Die Automatisierung wird nicht nur Ihren alten Joda-Time-Code transformieren, sondern auch den Teams helfen, 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 Standardization on java.time (JSR-310) erstellt, das Rezepte für die Migration von Joda-Time zu java.time auf eine weniger schmerzhafte Weise enthält. Dies ist ein wachsender Satz von Rezepten, den wir weiter ausbauen werden, um die Abdeckung mit weiteren Rezepten zu erhöhen.

Hier ist ein Beispiel für eine Migration, das Ihnen zeigt, wie Sensei die Migration von Legacy-Code vereinfacht.

Video zum Einstellen von java.time zoned date time

Von der sich wiederholenden manuellen Migration zu automatisierten Codeumwandlungen

Schauen wir uns ein Beispiel für die Erstellung einer neuen DateTime an, das ein paar versteckte Fallen bei der Migration einer einzigen Codezeile von Joda-Time zu java.time aufzeigt. Wir werden uns dann eines unserer Sensei Rezepte aus unserem Standardization on java.time (JSR-310) Kochbuch ansehen und zeigen, wie es all diese Informationen erfasst, so dass dieselbe Migration von jedem Entwickler wieder und wieder verwendet werden kann.

In diesem Beispiel konstruieren wir eine Joda-Time DateTime aus 7 int-Argumenten, die Werte der DateTime-Felder darstellen.

Wie können wir dies in ein java.time-Äquivalent migrieren?

Die Javadoc in Joda-Time für diesen Konstruktor sagt:

Konstruiert eine Instanz aus Datetime-Feldwerten unter Verwendung von ISOChronology in der Standardzeitzone.

Zunächst könnte man annehmen, dass es eine DateTime-Klasse in java.time gibt, aber das ist nicht der Fall. Wenn Sie nach "Migration von Joda-Time zu Java-Time" googeln, werden Sie höchstwahrscheinlich Stephen Colebournes Blogbeitrag Converting from Joda-Time to java.time finden.

Dies ist ein guter Anfang und weist uns den Weg zur Verwendung von java.time.ZonedDateTime oder java.time.OffsetDateTime. Hier stellt sich die erste Frage: Welche soll ich verwenden? Wahrscheinlich ZonedDateTime, basierend auf Stephens Kommentaren.

Wenn wir im Javadoc von ZonedDateTime nachsehen, können wir überhaupt keine Konstruktoren finden. Wir kehren zu Stephens Blogbeitrag zurück und lesen weiter unten:

Konstruktion. Joda-Time hat einen Konstruktor, der ein Objekt akzeptiert und eine Typkonvertierung durchführt. java.time hat nur Factory-Methoden, so dass die Konvertierung ein Benutzerproblem ist, obwohl eine parse()-Methode für Strings zur Verfügung steht.

Es muss also eine statische Fabrikmethode geben, und beim Durchsuchen der statischen Methoden finden wir eine, die ziemlich ähnlich aussieht, aber nicht genau dieselbe ist.

Er hat 7 int-Parameter wie unser ursprünglicher Joda-Time DateTime-Konstruktor, aber wenn Sie nicht aufpassen, werden Sie ein wichtiges Detail übersehen. Der 7. Parameter steht nicht mehr für Millisekunden, sondern für Nanosekunden. Das liegt daran, dass java.time die Genauigkeit gegenüber Joda-Time erhöht hat und Instanten auf die Nanosekunde genau misst. Ein wichtiges Detail, das Sie leicht hätten übersehen können. Außerdem erwartet diese Methode eine ZoneId, so dass man sich fragt, warum man vorher keine brauchte und warum man sie jetzt braucht.

Erinnern Sie sich an die Javadoc unserer ursprünglichen Konstruktor, die es würde die Standard-Zeitzone verwenden erwähnt, vielleicht gibt es eine Möglichkeit, die Standard-ZoneId zu erhalten?

In der Javadoc für ZoneId sind keine Konstruktoren aufgeführt, aber wenn wir uns die statischen Methoden ansehen, sehen wir, dass wir systemDefault()verwenden können

Nun, da wir die ZoneId geklärt haben, was sollen wir mit der Konvertierung von Millisekunden in NanoSekunden tun? Vielleicht können wir java.util.concurrent.TimeUnit verwenden, um die Umwandlung durchzuführen.

Diese Methode gibt einen long zurück, und unsere Methode erwartet einen int, so dass wir jetzt auch ein Konvertierungsproblem zu lösen haben. Vielleicht können wir etwas Einfaches versuchen. Eine Multiplikation?

Das funktioniert zwar, sieht aber ein wenig deplatziert aus. Falls Sie es noch nicht bemerkt haben: Wir haben viel Zeit und Mühe investiert, um eine einzige Codezeile zu migrieren. Aber wie Sie sich vorstellen können, müssen wir viele solcher Bearbeitungen 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 entdecken, die etwas flüssiger aussieht.

Obwohl ZonedDateTime keine offensichtliche Möglichkeit bietet, die Millisekunden zu setzen, kann dies mit der Methode with(TemporalField field, long newValue) erfolgen, wobei ChronoField.MILLI_OF_SECOND als TemporalField verwendet wird.

Und in der Java-Doku wird erwähnt, dass es die Konvertierung in Nanosekunden für uns durchführt:

Wenn dieses Feld zur Einstellung eines Wertes verwendet wird, sollte es sich genauso verhalten wie die Einstellung von NANO_OF_SECOND, wobei der Wert mit 1.000.000 multipliziert wird.

Wir können also einfach 0 für unsere Nanosekunden in der Factory-Methode angeben und dann die With-Methode verwenden, um eine ZonedDateTime zu erstellen, die alle ursprünglichen Werte sowie die Millisekunden enthält.

Wenn man sich unser Endergebnis ansieht, sieht es so aus, als hätten wir nur eine einzige Codezeile geändert. Das zeigt nicht wirklich den Aufwand, der mit der Erforschung einer einzigen Migration verbunden war!

Erstellen Sie ein Rezept, um schneller und einfacher zu migrieren

Sensei bietet uns die Möglichkeit, diese hart erarbeiteten Informationen mit anderen Entwicklern zu teilen. Durch die Erstellung eines Rezepts, in dem all diese Anforderungen erfasst sind, können die Benutzer von Sensei diese Migration mit einem Mausklick durchführen.

Ein Sensei Rezept besteht aus 3 Hauptteilen:

  • Metadaten
  • Suche
  • AvailableFixes

Schauen wir uns ein Sensei Rezept an (kann auch als YAML-Rezept betrachtet werden), das uns hilft, diesen Aufruf in sein java.time-Äquivalent zu migrieren.

DateTime foo = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond);

Abschnitt Metadaten

Der Abschnitt Metadaten enthält Informationen über das Rezept und seine Verwendung.

Bereich Suche

Der Suchabschnitt eines Sensei Rezepts gibt an, auf welche Code-Elemente dieses 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 Suchabschnitt sehen wir, dass wir es sind:

  • Suche nach einer instanceCreation, d.h. einer Verwendung eines Constructors. Hinweis: Es sind viele andere Suchziele verfügbar
  • Der Konstruktor sollte 7 Argumente haben, dies wird durch die Eigenschaft argCount angegeben
  • args 1-7 sollten vom Typ int sein
  • Wir suchen nach Konstruktoren vom Typ 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. Jede Korrektur kann mehrere Aktionen haben, und in unserem Fall haben wir eine einzige Korrektur, die 2 Aktionen ausführt.

  • Der Name des Fixes wird dem Benutzer im Menü "Quickfixes" angezeigt und beschreibt, was passiert, wenn der Benutzer diesen Quickfix anwendet
  • Die Liste der Aktionen zeigt, welche Aktionen durch diesen Quickfix ausgeführt werden
  • Die Rewrite-Aktion schreibt das Code-Element unter Verwendung einer Mustache-Vorlage um. Dabei können Variablen und Funktionen zur Ersetzung von Zeichenketten verwendet werden.
  • Die Aktion modifyAssignedVariable prüft, ob dieser Konstruktor verwendet wird, um einer Variablen einen Wert zuzuweisen. Wenn dies der Fall ist, ändert diese Aktion die Variable so, dass sie als der Typ deklariert wird, der durch type

Verwendung des Rezepts für die Codeumwandlung

Wenn unser Rezept geschrieben und aktiviert ist, scannt es unseren Code und markiert die Segmente, auf die es angewendet werden kann.

Im folgenden Screenshot sehen wir, dass der Zielkonstruktor mit Sensei markiert wurde. Wenn wir den Mauszeiger über den markierten Konstruktor bewegen, sehen wir die Recipe shortDescription und die Quickfix-Option Migrate to java.time.ZonedDateTime

Migrieren Neues Datum Uhrzeit

Nachdem wir den Quickfix Migrate to java.time.ZonedDateTime ausgewählt haben, wird der Code entsprechend den im Rezept angegebenen Aktionen umgewandelt.

Zonen Datum Uhrzeit mit Jahr Monat Tag Stunde

Eine einmalige Migration und einheitliche Kodierungspraktiken in allen Teams - mit Sensei

Wie wir an unserem obigen Beispiel sehen, kann die Migration einer einzigen Codezeile hart erarbeitetes Wissen beinhalten. 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, inkrementelle, sofortige Transformationen zu 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 Migration von Bibliotheken ist nur ein Beispiel für die vielen Möglichkeiten, die Sensei bietet, um Ihre Projekte zu standardisieren. Sie können immer nach Anti-Patterns oder bestimmten manuellen Code-Transformationen Ausschau halten, auf die Sie häufig in Pull-Requests oder beim Coding selbst stoßen. Wenn Sie über eine Reihe von Codierungsrichtlinien verfügen, die von den Entwicklern häufig übersehen werden, können Sie diese Richtlinien in Rezepte umwandeln, so dass die Entwickler bewährte Codeumwandlungen sicher anwenden können.

Wenn Sie Fragen haben, würden wir uns freuen, von Ihnen zu hören! Treten Sie uns auf Slack bei: sensei-scw.slack.com

Inhaltsübersicht

PDF herunterladen
Ressource anzeigen
Interessiert an mehr?

Cameron ist ein leitender Softwareentwickler bei Secure Code Warrior. Er verfügt über mehr als 15 Jahre Erfahrung in der Bereitstellung von Software. Er setzt sich leidenschaftlich für die Produktivität von Entwicklern ein und trägt aktiv zu Open-Source-Software bei.

Secure Code Warrior ist für Ihr Unternehmen da, um Sie dabei zu unterstützen, Ihren Code über den gesamten Lebenszyklus der Softwareentwicklung hinweg zu sichern und eine Kultur zu schaffen, in der Cybersicherheit an erster Stelle steht. Ganz gleich, ob Sie AppSec-Manager, Entwickler, CISO oder ein anderer Sicherheitsverantwortlicher sind, wir können Ihrem Unternehmen helfen, die mit unsicherem Code verbundenen Risiken zu reduzieren.

Demo buchenHerunterladen
Weitergeben:
Ressourcendrehscheibe

Ressourcen für den Einstieg

Mehr Beiträge
Ressourcendrehscheibe

Ressourcen für den Einstieg

Mehr Beiträge