Blog

Migración de Joda-Time a java.time

November 12, 2021
Cameron Gregor

Migrar código (léase: código heredado) no es divertido. Se necesita una enorme cantidad de planificación y esfuerzo para lograrlo. Si bien no es el trabajo más emocionante o motivador para los desarrolladores, sí que requiere determinación y la experiencia adecuada para migrar el código heredado a las nuevas versiones de la biblioteca. Hora de Joda a java.time es una de esas migraciones que requiere una planificación y ejecución meticulosas.

Si su proyecto Java comenzó su vida antes de Java SE 8 y utiliza el procesamiento de fecha y hora, es probable que haya utilizado Joda-Time, una biblioteca excelente y un estándar de facto para gestionar las funciones de fecha y hora anteriores a SE 8. Si tu proyecto Aún así usa Joda-Time pero le gustaría migrar a java.time y luego siga leyendo.

La versión de Java SE 8 incluía una API de fecha y hora estándar nueva y mejorada, comúnmente denominada java.time (JSR-310). El proyecto Joda-Time ahora recomienda migrar a java.time (JSR-310).

Si bien java.time (JSR-310) se inspiró en gran medida en Joda-Time, no es compatible con versiones anteriores y los conceptos y terminologías han cambiado. Por eso, migrar de Joda-Time a java.time requiere prestar mucha atención a todas y cada una de las líneas de código que cambias. Esto puede llevar mucho tiempo y casi haría que deseara que hubiera una forma más fácil y automatizada de migrar.

Hay una forma mejor de migrar y la hemos creado con Sensei, un complemento de IntelliJ que realiza automáticamente transformaciones de código según las recetas (reglas) definidas por usted. Dedica tu tiempo a definir recetas reutilizables, en lugar de a realizar tareas de migración repetitivas. La automatización no solo transformará tu código heredado de Joda-Time, sino que también ayudará a los equipos a seguir las directrices que aparecen en el IDE a medida que escriben código nuevo.

Para ayudarlo a comenzar con ventaja, hemos creado un libro de cocina público sobre Sensei Estandarización en java.time (JSR-310) que incluye recetas para migrar de Joda-Time a java.time de una manera menos dolorosa. Se trata de un conjunto de recetas cada vez mayor que seguiremos ampliando para añadir más cobertura con más recetas.

Este es un ejemplo de un ejemplo de migración que puede ayudarle a ver cómo Sensei facilita la migración del código heredado.

Video of how to set java.time zoned date time

Desde la migración manual repetitiva hasta las transformaciones de código automatizadas

Veamos un ejemplo de creación de un nuevo DateTime que muestra algunas trampas ocultas al migrar una sola línea de código de Joda-Time a java.time. A continuación, analizaremos una de las recetas de Sensei de nuestro libro de recetas sobre la estandarización de java.time (JSR-310) y mostraremos cómo captura toda esta información para que cualquier desarrollador pueda volver a utilizar esta misma migración una y otra vez.

En este ejemplo, estamos construyendo un Joda-Time DateTime a partir de 7 argumentos int que representan los valores de los campos DateTime.

¿Cómo migramos esto a un equivalente de java.time?

El javadoc en Joda-Time para este constructor dice:

Construye una instancia a partir de los valores de los campos de fecha y hora utilizando IsoChronology en la zona horaria predeterminada.

Al principio, podemos suponer que hay Fecha/hora clase en java.time, pero no hay ninguna. Si buscas en Google «migrar de la hora de Joda a la hora de Java», lo más probable es que encuentres la entrada del blog de Stephen Colebourne Conversión de Joda-Time a java.time.

Esto le da un buen comienzo y nos indica cómo usar java.time.zonedDateTime o java.time.offsetDateTime. Esta es nuestra primera pregunta, ¿cuál uso? Probablemente ZonedDateTime se basa en los comentarios de Stephen.

Buscando el ZonedDateTime javadoc, no podemos ver ningún constructor en absoluto. Volviendo a la entrada del blog de Stephen, leemos más abajo:

Construcción. Joda-Time tiene un constructor que acepta un objeto y realiza la conversión de tipos. java.time solo tiene métodos de fábrica, por lo que la conversión es un problema del usuario, aunque se proporciona un método parse () para las cadenas.

Por lo tanto, debe haber un método de fábrica estático, al buscar los métodos estáticos encontramos uno que se parece bastante, pero no es exactamente el mismo.

Tiene 7 parámetros int como nuestro constructor Joda-Time DateTime original, sin embargo, si no prestas atención, te perderás un detalle importante. El séptimo parámetro ya no representa milisegundos, sino nanosegundos, ya que java.time tiene una precisión mayor que Joda-Time y mide los instantes hasta el nano-segundo. Un detalle importante que podrías haber pasado por alto fácilmente. Además, este método espera un ZoneID, por lo que hace que te preguntes por qué no necesitabas uno antes y por qué lo necesitas ahora.

Recordando el javadoc de nuestro constructor original que mencionaba que usaría la zona horaria predeterminada, ¿tal vez haya una forma de obtener el ZoneID predeterminado?

El javadoc para ZoneID no nos informa sobre ningún constructor de la lista, pero al observar los métodos estáticos vemos que podemos usar Predeterminado del sistema ()

Ahora que hemos resuelto el ZoneID, ¿qué debemos hacer con nuestra conversión de milisegundos a nanosegundos? Tal vez podamos usar java.util.Concurrent.TimeUnit para realizar la conversión.

Este método devuelve un valor long y nuestro método espera un int, por lo que ahora también tenemos que resolver un problema de conversión. Tal vez podríamos probar algo simple. ¿Una multiplicación?

Esto funcionará, pero parece un poco fuera de lugar. Si aún no lo has notado, hemos dedicado una cantidad considerable de tiempo y esfuerzo a migrar una sola línea de código. Pero como puedes imaginar, tenemos muchas ediciones de este tipo que hacer a mano y no hay nada mejor.

Sin embargo, si analizamos un poco más la API java.time, podemos descubrir una solución que parece un poco más fluida.

Aunque ZonedDateTime no tiene una forma obvia de configurar los milisegundos, se puede hacer usando el con el método (campo temporalField, newValue largo), utilizando Cronofield. Mili_de_segundo como TemporalField.

Y el documento de Java menciona que realizará la conversión a nanosegundos por nosotros:

Cuando este campo se usa para establecer un valor, debe comportarse de la misma manera que si se establece NANO_OF_SECOND con el valor multiplicado por 1 000 000.

Así que podemos simplemente especificar 0 para nuestros nanosegundos en el método de fábrica y, a continuación, usar el con método para crear un ZonedDateTime que tenga todos los valores originales, así como los milisegundos.

Al observar nuestro resultado final, parece que solo hemos cambiado una línea de código, ¡realmente no muestra el esfuerzo que se dedicó a investigar solo una migración!

Cree una receta para migrar de forma más rápida y sencilla

Sensei nos proporciona una forma de compartir esta información ganada con tanto esfuerzo con otros desarrolladores. Al crear una receta que recoja todos estos requisitos, permitirá a los usuarios de Sensei realizar esta migración con solo un clic del ratón.

Una receta de Sensei consta de 3 secciones principales:

  • Metadatos
  • Búsqueda
  • Correcciones disponibles

Veamos una receta de Sensei (también se puede ver como una receta de YAML) que nos ayudará a migrar esta llamada a su equivalente en java.time.

DateTime foo = nueva fecha y hora (año, mes del año, día del mes, hora del día, minuto de hora, segundo de minuto, milisegundo de segundo);

Sección de metadatos

La sección de metadatos contiene información sobre la receta y cómo debe usarse.

Sección de búsqueda

La sección de búsqueda de una receta de Sensei especifica a qué elementos de código se debe aplicar esta receta.

buscar:
Creación de instancias:
argumentos:
1:
tipo: int
2:
tipo: int
3:
tipo: int
4:
tipo: int
5:
tipo: int
6:
tipo: int
7:
tipo: int
Recuento de arg: 7
tipo: org.joda.time.DateTime

En esta sección de búsqueda vemos que estamos:

  • En busca de un Creación de instancias, es decir, el uso de un Constructor. Nota: hay muchos otros objetivos de búsqueda disponibles
  • El constructor debe tener 7 argumentos, esto se especifica en Recuento de arg propiedad
  • argumentos 1-7 debe ser de tipo int
  • Estamos buscando a los constructores del tipo org.joda.time.dateTime

Sección de correcciones disponibles

La sección AvailableFixes puede especificar una o más correcciones que se pueden aplicar al elemento de código coincidente. Cada corrección puede tener varias acciones y, en nuestro caso, tenemos una única solución que realiza 2 acciones.

  • El nombre de la solución se muestra al usuario en el menú «Correcciones rápidas» y describe lo que ocurrirá si el usuario aplica esta solución rápida
  • La lista de acciones muestra las acciones que realizará esta solución rápida.
  • El volver a escribir la acción reescribirá el elemento de código utilizando una plantilla de bigote. Puede hacer uso de variables y funciones de reemplazo de cadenas.
  • El Modificar variable asignada action comprobará si este constructor se utiliza para asignar el valor a una variable. Si es así, esta acción modificará la variable para declararla como el tipo especificado por tipo

Uso de la receta para realizar la transformación del código

Con nuestra receta escrita y habilitada, escanea nuestro código y resalta los segmentos a los que se puede aplicar.

En la siguiente captura de pantalla podemos ver que el constructor objetivo ha sido marcado por Sensei. Al pasar el ratón sobre el constructor marcado, aparecen la opción Recipe ShortDescription y Quickfix Migrar a java.time.ZonedDateTime

Migrate New Date Time

Después de seleccionar el Migrar a java.time.ZonedDateTime Quickfix, el código se transforma de acuerdo con las acciones que especificamos en la receta.

Zoned Date Time With Year Month Day Hour

Una migración única y prácticas de codificación uniformes en todos los equipos, con Sensei

En nuestro ejemplo anterior, podemos ver que la migración de una sola línea de código puede implicar un conocimiento adquirido con esfuerzo. Sensei puede convertir ese conocimiento en recetas prácticas o libros de cocina que puedan compartirse entre equipos. Puedes planificar una migración rápida única o adoptar el enfoque de realizar transformaciones instantáneas incrementales a java.time a medida que te encuentres con el código de Joda-Time. Puedes activar o desactivar las recetas para realizar las migraciones por etapas o pasos lógicos e incluso ampliar o reducir el alcance de los archivos analizados por Sensei, con la flexibilidad que hace que las migraciones de código sean menos complicadas.

La migración de bibliotecas es solo un ejemplo de las muchas maneras en las que se puede usar Sensei para estandarizar sus proyectos. Siempre puedes estar atento a los antipatrones o a ciertas transformaciones manuales de código que aparecen con frecuencia en las solicitudes de cambios o mientras codificas tú mismo. Si tienes un conjunto de directrices de codificación que los desarrolladores suelen pasar por alto, podrías convertir las directrices en recetas, lo que permitiría a los desarrolladores aplicar las transformaciones de código aprobadas con confianza.

Si tiene alguna pregunta, ¡nos encantaría saber de usted! Únete a nosotros en Slack en: sensei-scw.slack.com

Lema

Govern AI-driven development before it ships

Measure AI-assisted risk, enforce secure coding policy at commit, and accelerate secure delivery across your SDLC.

book a demo
Lema

Explore more blogs

Lorem ipsum diam quis enim lobortis scelerisque fermentum dui faucibus in ornare quam viverra orci sagittis eu volutpat odio facilisis.

browse all
Case Study
Filter Label
This is some text inside of a div block.

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.

Learn More
Case Study
Filter Label
This is some text inside of a div block.

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

Learn More
Case Study
Filter Label
This is some text inside of a div block.

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.

Learn More
Blog
Filter Label
This is some text inside of a div block.

El futuro de la gobernanza de software de IA se construye sobre asociaciones sólidas

Descubra por qué Secure Code Warrior se está convirtiendo en una empresa centrada en el canal y cómo los socios de confianza ayudan a las organizaciones a adoptar la gobernanza de software de IA de forma segura y a escala.

Learn More
Blog
Filter Label
This is some text inside of a div block.

Citizen AI de Secure Code Warrior: Crea una fuerza laboral preparada para la IA

Programa de alfabetización en IA de Secure Code Warrior para empleados que no son desarrolladores.

Learn More
Blog
Filter Label
This is some text inside of a div block.

Por qué la mayoría de los CISO navegan a ciegas en la adopción de la IA (y cómo pueden quitarse la venda)

Hoy, Secure Code Warrior ha publicado un nuevo informe técnico que presenta un modelo prescriptivo y orientativo de adopción de IA, diseñado para que los líderes de seguridad puedan identificar su etapa de adopción y avanzar de forma efectiva en el control de los riesgos de seguridad relacionados con la IA en sus organizaciones.

Learn More

Secure AI-driven development before it ships

See developer risk, enforce policy, and prevent vulnerabilities across your software development lifecycle.

Book a demo