Joda-Time: qué es, la biblioteca de fechas y su reemplazo con Java 8

Autor: IT Sectr Publicado: 2026-07-14 Tiempo de lectura: 10 min

Joda-Time es una biblioteca para trabajar con fechas y horas en Java, creada por Stephen Colebourne como alternativa a los engorrosos java.util.Date y java.util.Calendar. Antes del lanzamiento de Java 8, esta biblioteca era el estándar de facto para el manejo de fechas en el desarrollo industrial, incluidas las aplicaciones Android. Según Oracle Java Magazine (2023), más del 60% de los proyectos migraron de Joda-Time a java.time en los dos años posteriores al lanzamiento de Android API 26.

Puntos clave

  • Joda-Time es una biblioteca para trabajar con fechas y horas, predecesora de java.time en Java 8
  • Clases inmutables — DateTime, LocalDate, LocalTime, LocalDateTime garantizan la seguridad en hilos
  • Soporte de zonas horarias — base de datos de zonas horarias integrada con actualizaciones automáticas
  • Migración — java.time (JSR-310) reemplaza completamente a Joda-Time, los autores de la biblioteca recomiendan la transición
  • Android — Joda-Time funciona desde API 1, pero para Android 8+ (API 26) se prefiere java.time

¿Qué es Joda-Time?

Joda-Time es una biblioteca de código abierto (Apache 2.0) que proporciona un reemplazo de calidad para las clases java.util.Date y java.util.Calendar en el lenguaje Java. El proyecto fue fundado por Stephen Colebourne en 2004 en respuesta a los numerosos problemas de las API estándar de fecha y hora, incluyendo la mutabilidad, la complejidad del formato y el soporte limitado de zonas horarias. La biblioteca ganó una amplia adopción en la comunidad Java y fue utilizada por miles de proyectos, incluyendo grandes sistemas empresariales y aplicaciones Android, donde las herramientas integradas para el manejo de fechas eran especialmente incómodas. Desde el lanzamiento de Java 8 en 2014 y la introducción del paquete java.time (JSR-310), la biblioteca ha pasado a modo de mantenimiento — no se agregan nuevas funciones y la funcionalidad existente está completamente cubierta por la nueva API.

Arquitectura de la biblioteca

Joda-Time está construida sobre el principio de inmutabilidad: cada objeto de fecha u hora no puede modificarse después de su creación. Cualquier operación — agregar un día, cambiar un mes, establecer una zona horaria — devuelve un nuevo objeto, dejando el original sin cambios. Este enfoque elimina por completo la clase de errores asociados con la modificación no intencional de objetos que eran característicos de los mutables java.util.Date y java.util.Calendar. El diseño inmutable también hace que la biblioteca sea segura para hilos sin necesidad de sincronización adicional.

Clases principales de Joda-Time

La biblioteca proporciona varias clases principales para diferentes escenarios: DateTime — fecha y hora completa con zona horaria, LocalDate — solo fecha sin hora, LocalTime — solo hora sin fecha, LocalDateTime — fecha y hora sin vinculación a zona horaria. Además, se incluyen clases para trabajar con intervalos (Interval), períodos (Period) y duraciones (Duration), que permiten calcular la diferencia entre dos momentos en el tiempo en varias unidades de medida. Cada clase implementa la interfaz ReadableInstant o ReadablePartial para un manejo uniforme.

Historia de Joda-Time

El problema de las API estándar de fecha en Java era conocido desde los inicios de la plataforma. Las clases java.util.Date y java.util.Calendar tenían fallos fundamentales: los meses se numeraban desde 0, Date representaba simultáneamente fecha y hora, Calendar era mutable y requería una configuración compleja. El formato a través de SimpleDateFormat no era seguro para hilos — en aplicaciones multihilo esto provocaba un análisis incorrecto de las fechas. Stephen Colebourne, trabajando en proyectos con uso intensivo de fechas, decidió crear una alternativa que solucionara todos estos problemas.

Según una entrevista en InfoQ (2014), Colebourne probó Joda-Time en proyectos de producción durante más de un año antes del primer lanzamiento público. La primera versión se publicó en 2004 e inmediatamente atrajo la atención de la comunidad. Para 2010, la biblioteca se había convertido en una dependencia estándar en la mayoría de los proyectos Java, incluidos frameworks como Spring y Hibernate. El éxito de Joda-Time influyó directamente en la especificación JSR-310 (Date and Time API), que se incluyó en Java 8 — con el mismo Stephen Colebourne como líder de la especificación.

Impacto en el ecosistema Java

Joda-Time no solo resolvió el problema de las fechas — cambió el enfoque del diseño de API en Java. El concepto de objetos de valor inmutables, demostrado por la biblioteca, fue adoptado como estándar en Java 8 para todas las nuevas API. Además, la popularidad de Joda-Time mostró a Oracle que la comunidad no estaba dispuesta a tolerar bibliotecas estándar de baja calidad — después de Joda-Time, se rediseñaron las API de Java para manejo de archivos (NIO.2), tiempo (java.time) y valores opcionales (Optional).

Características clave de la biblioteca Joda-Time

Joda-Time proporciona un conjunto de características que no estaban disponibles en la biblioteca estándar antes de Java 8. Las ventajas principales incluyen soporte para más de 200 zonas horarias con manejo automático del horario de verano, una API de formato rica con patrones y configuraciones regionales, así como cálculos de períodos entre fechas en varias unidades — años, meses, días, horas. Mención especial merece el sistema de intervalos: Interval (un lapso entre dos instantes), Period (diferencia en unidades de calendario) y Duration (duración exacta en milisegundos).

Formato y análisis

La clase DateTimeFormatter en Joda-Time proporciona un formato de fechas seguro para hilos — a diferencia de java.text.SimpleDateFormat. Los formateadores se pueden crear mediante patrones (por ejemplo, “yyyy-MM-dd HH:mm:ss”) o mediante estilos (SHORT, MEDIUM, LONG, FULL) para una salida localizada. La biblioteca también admite el almacenamiento en caché de formateadores, lo que acelera el rendimiento en aplicaciones de alta carga. El análisis de fechas a partir de cadenas se realiza con control de rigor — se pueden permitir o rechazar fechas incompletas o incorrectas.

Intervalos y cálculos

Uno de los puntos fuertes de Joda-Time es el trabajo con intervalos de tiempo. La clase Interval representa un lapso de tiempo exacto entre dos instantes y admite operaciones de intersección, unión y verificación de contención. Period, a diferencia de Interval, opera en unidades de calendario — por ejemplo, la diferencia entre el 1 de marzo y el 1 de abril es exactamente 1 mes, aunque en duración podrían ser 28–31 días. Duration, por otro lado, representa una duración exacta en milisegundos sin vinculación al calendario y es adecuada para medir el tiempo de ejecución de operaciones.

java
import org.joda.time.*;
import org.joda.time.format.*;

DateTime now = new DateTime();
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
String formatted = fmt.print(now);

DateTime nextWeek = now.plusWeeks(1);
Period period = new Period(now, nextWeek);
int days = period.getDays(); // días = 7

Interval interval = new Interval(now, nextWeek);
boolean contains = interval.contains(now); // verdadero

Comparación entre Joda-Time y java.time

El paquete java.time (JSR-310) fue desarrollado por el mismo autor — Stephen Colebourne — e incorporó las mejores ideas de Joda-Time con diez años de experiencia operativa. Ambas API utilizan clases inmutables, admiten zonas horarias y proporcionan un rico conjunto de operaciones. Sin embargo, java.time está completamente integrado en la biblioteca estándar de Java, no requiere dependencias externas y utiliza un sistema de nomenclatura más consistente: Instant en lugar de ReadableInstant, LocalDate en lugar de LocalDate (nombre conservado), ZonedDateTime en lugar de DateTime.

CaracterísticaJoda-Timejava.time
Año de lanzamiento20042014 (Java 8)
EstadoMantenimientoDesarrollo activo
Fecha/hora baseDateTimeZonedDateTime
Solo fechaLocalDateLocalDate
Inmutabilidad
FormatoDateTimeFormatterDateTimeFormatter
Diferencia de fechasPeriod / DurationPeriod / Duration

Diferencias clave

java.time corrige varias decisiones arquitectónicas de Joda-Time. En primer lugar, java.time elimina la confusión entre métodos que devuelven null y valores ausentes — usando Optional en su lugar. En segundo lugar, se ha agregado soporte para sistemas de calendario alternativos (japonés, tailandés, islámico) a través de la interfaz Chronology. En tercer lugar, java.time incluye la clase Instant para trabajar con instantes de tiempo UTC sin vinculación al calendario — esto simplifica la integración con protocolos de red y bases de datos. Para Android, se recomienda usar java.time a partir de API 26 (Android 8.0) o mediante desugaring para versiones anteriores.

Migración de Joda-Time a java.time

La migración de Joda-Time a java.time es un proceso que los autores de la biblioteca intentaron hacer lo más seguro y predecible posible. La mayoría de las clases tienen contrapartes directas: DateTime → ZonedDateTime, LocalDate → LocalDate (el nombre coincide), LocalTime → LocalTime, DateTimeZone → ZoneId, Period → Period, Duration → Duration. Los cambios principales afectan la forma de crear objetos y los nombres de métodos — por ejemplo, en lugar de `now.toDate()`, se usa `Date.from(instant)`, y `DateTime.now()` se reemplaza con `ZonedDateTime.now()`.

Estrategia de migración paso a paso

Se recomienda comenzar la migración aislando Joda-Time en una capa de abstracción delgada — esto permite reemplazar la biblioteca de forma incremental sin tocar toda la base de código. El primer paso suele ser reemplazar el trabajo con LocalDate y LocalTime — estas clases tienen la menor cantidad de diferencias entre bibliotecas. La segunda etapa migra DateTime (a ZonedDateTime) y las zonas horarias. La tercera etapa reemplaza Interval, Period y Duration — aquí hay que verificar cuidadosamente el comportamiento con el horario de verano. Después de completar la migración, Joda-Time se elimina por completo de las dependencias del proyecto.

kotlin
// Joda-Time (antes de la migración)
val dateTime = DateTime.now(DateTimeZone.forID("Europe/Moscow"))
val formatted = dateTime.toString("dd.MM.yyyy")
val plusDay = dateTime.plusDays(1)

// java.time (después de la migración)
val zonedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Moscow"))
val formatted2 = zonedDateTime.format(
    DateTimeFormatter.ofPattern("dd.MM.yyyy")
)
val plusDay2 = zonedDateTime.plusDays(1)

Herramientas de migración

Existen varias utilidades que simplifican la transición de Joda-Time a java.time. OpenRewrite (de Moderne) admite la migración automática mediante la receta org.openrewrite.java.migrate.JodaTimeToJavaTime — reemplaza clases, métodos e importaciones preservando la lógica del programa. Para proyectos Gradle, el plugin de.fayard.refreshVersions también incluye reglas de migración. Manualmente, la migración es más fácil de realizar con IDEA: el plugin Java Time Migration Assistant resalta las llamadas a Joda-Time y sugiere las sustituciones correspondientes en java.time, acelerando el proceso de 2 a 3 veces en comparación con el reemplazo manual.

Ejemplos de código con Joda-Time

Veamos ejemplos prácticos de trabajo con Joda-Time en aplicaciones Android. La biblioteca es especialmente útil para formatear fechas según estándares locales, calcular la edad del usuario, determinar la duración de eventos y calcular intervalos entre dos fechas. Todos los ejemplos utilizan objetos inmutables — cada llamada devuelve una nueva instancia, mientras que el objeto original permanece sin cambios.

kotlin
// Calcular edad del usuario
val birthDate = LocalDate.parse("1990-05-15")
val today = LocalDate.now()
val age = Years.yearsBetween(birthDate, today).getYears()
// edad == 36

// Formatear con configuración regional del usuario
val dateTime = DateTime.now()
val formatter = DateTimeFormat.forStyle("MM").withLocale(Locale.getDefault())
val localized = formatter.print(dateTime)

Trabajo con intervalos

Los intervalos en Joda-Time permiten resolver de manera eficiente tareas como verificar la superposición de intervalos de tiempo, calcular intersecciones y encontrar el evento más cercano. Por ejemplo, al desarrollar una aplicación de calendario, se puede verificar si un nuevo evento se superpone con los existentes. La clase Interval admite las operaciones contains, overlaps, gap y abuts — esta última muestra si los intervalos se tocan en sus límites. Duration se utiliza para medir la duración entre dos instantes con precisión de milisegundos.

java
// Verificar superposición de intervalos
Interval meeting1 = new Interval(
    new DateTime(2026, 7, 21, 10, 0),
    new DateTime(2026, 7, 21, 11, 0)
);
Interval meeting2 = new Interval(
    new DateTime(2026, 7, 21, 10, 30),
    new DateTime(2026, 7, 21, 11, 30)
);

boolean overlaps = meeting1.overlaps(meeting2); // verdadero
Duration gap = meeting1.gap(meeting2); // null (sin espacio)

Preguntas frecuentes

¿Qué es Joda-Time y para qué sirve?

Joda-Time es una biblioteca para trabajar con fechas y horas en Java, creada antes del lanzamiento de Java 8. Corrigió las deficiencias de java.util.Date y java.util.Calendar: mutabilidad, numeración de meses desde 0, falta de soporte completo de zonas horarias y formato no seguro para hilos.

¿En qué se diferencia Joda-Time de java.time?

Java.time (JSR-310) es el sucesor de Joda-Time, desarrollado por el mismo autor. Las principales diferencias: java.time está integrado en la biblioteca estándar de Java 8+, utiliza un sistema de nomenclatura más consistente, admite sistemas de calendario alternativos e incluye la clase Instant para trabajar con tiempo UTC.

¿Debería usar Joda-Time en nuevos proyectos?

No, para proyectos nuevos se recomienda usar java.time. Joda-Time está en modo de mantenimiento desde 2014 y ya no recibe nuevas funciones. Para Android con API 26+, java.time está disponible de forma nativa, y para versiones anteriores se utiliza desugaring — un mecanismo que permite usar java.time en dispositivos con API 19+.

¿Cómo migrar código de Joda-Time a java.time?

La migración se realiza paso a paso: aísle Joda-Time en abstracciones, reemplace primero LocalDate y LocalTime, luego DateTime → ZonedDateTime, y finalmente Period, Duration e Interval. La herramienta OpenRewrite admite la migración automática mediante la receta JodaTimeToJavaTime, acelerando el proceso de 2 a 3 veces.

¿Qué clases de Joda-Time corresponden a java.time?

DateTime → ZonedDateTime, LocalDate → LocalDate (coincide), LocalTime → LocalTime, LocalDateTime → LocalDateTime, DateTimeZone → ZoneId, Interval → no tiene equivalente directo (se usa una combinación de Instant + Duration), Period → Period, Duration → Duration. Los nombres de métodos también son similares: plusDays, minusMonths, withZone están disponibles en ambas bibliotecas.

Resumen

  • Joda-Time es una biblioteca de fechas y horas para Java que se convirtió en el estándar antes de Java 8 e influyó directamente en la especificación JSR-310
  • Diseño inmutable — todas las clases de Joda-Time son inmutables, lo que garantiza la seguridad en hilos y evita mutaciones accidentales de objetos
  • Clases principales — DateTime, LocalDate, LocalTime, LocalDateTime, Period, Duration e Interval cubren todos los escenarios de fecha y hora
  • Soporte de zonas horarias — base de datos integrada de más de 200 zonas horarias con manejo automático del horario de verano y actualizaciones
  • Migración a java.time — recomendada para todos los proyectos; se realiza de forma incremental usando herramientas OpenRewrite y funciones integradas del IDE
  • Compatibilidad con Android — Joda-Time funciona desde API 1, pero para API 26+ se prefiere java.time, disponible mediante desugaring en versiones anteriores
  • Importancia histórica — Joda-Time cambió el enfoque del diseño de API en Java y demostró a la comunidad los beneficios de los objetos de valor inmutables

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también