Introducción
Antes de Java 1.8, el manejo de fechas y horas en Java era complicado y propenso a errores. Las clases Date y Calendar tenían limitaciones y problemas de diseño. Con la llegada de Java 1.8, se introdujo una nueva API de fechas y horas en el paquete java.time, más moderna, intuitiva, robusta y flexible.
En esta entrada, vamos a explorar cómo trabajar con fechas en Java 1.8, explicando las clases más importantes, sus métodos y por qué esta nueva API es la mejor opción para manejar fechas y horas.
¿Qué vamos a aprender hoy?
- Por qué java.time es tu mejor amigo (y no java.util.Date).
 - Las clases principales para representar fechas y horas: LocalDate, LocalTime, LocalDateTime, ZonedDateTime.
 - Cómo crear fechas y horas: Desde cero y a partir de cadenas de texto.
 - Cómo obtener información de una fecha: Día, mes, año, etc.
 - Cómo manipular fechas: Sumar, restar, comparar.
 - Formateo: Cómo mostrar las fechas en el formato que necesites (ej: «12/01/2024»).
 - Zonas horarias: Cómo manejar fechas en diferentes partes del mundo.
 
¿Por qué usar java.time en lugar de Date o Calendar?
Las clases Date y Calendar presentaban varias desventajas:
- Mutabilidad: Eran mutables, lo que podía llevar a errores en aplicaciones concurrentes.
 - Complejidad: Su uso era poco intuitivo y propenso a errores.
 - Limitaciones: Carecían de soporte adecuado para zonas horarias y operaciones comunes con fechas.
 
La nueva API java.time aborda estos problemas proporcionando clases inmutables y un diseño más claro y robusto. 
- Inmutabilidad: Las clases de 
java.timeson inmutables, lo que significa que no pueden modificarse después de su creación. Los objetos java.time no se modifican directamente. Cuando sumas un día a una fecha, creas un nuevo objeto. Esto evita errores inesperados y facilita la depuración. Imagina que intentas modificar un String. No puedes, siempre creas uno nuevo. Lo mismo ocurre con las fechas en java.time. Esto evita errores comunes en programas concurrentes. - Claridad y facilidad de uso: La nueva API es mucho más intuitiva y fácil de entender. Los nombres de los métodos son descriptivos y separa claramente los conceptos de fecha, hora y fecha-hora.
 - Thread-safe: Seguro para usar en programas con múltiples hilos de ejecución (un tema que veréis más adelante, ¡pero es importante!).
 - Flexibilidad: Proporciona métodos para realizar cálculos y manipulaciones de fechas de manera sencilla.
 - Mejor Manejo de Zonas Horarias: Simplifica el trabajo con fechas en diferentes zonas horarias.
 - Compatibilidad con estándares: Sigue el estándar ISO-8601, que es ampliamente utilizado en todo el mundo.
 
Clases Principales de la API java.time
Las clases más importantes de la API java.time son:
LocalDate: Representa una fecha (año, mes, día) sin hora.LocalTime: Representa una hora (hora, minuto, segundo) sin fecha.LocalDateTime: Combina fecha y hora, pero sin zona horaria.ZonedDateTime: Representa una fecha y hora con zona horaria.Instant: Representa un punto específico en el tiempo (timestamp) en UTC.Duration: Representa una cantidad de tiempo en segundos y nanosegundos.Period: Representa una cantidad de tiempo en años, meses y días.
A continuación, se presentan las clases más utilizadas de la nueva API:
1. LocalDate
LocalDate es ideal para representar fechas sin hora, como fechas de nacimiento o fechas de eventos. 
Ejemplo de uso:
import java.time.LocalDate;
public class EjemploLocalDate {
    public static void main(String[] args) {
        // Fecha actual
        LocalDate hoy = LocalDate.now();
        System.out.println("Fecha actual: " + hoy);
        // Crear una fecha específica
        LocalDate nacimiento = LocalDate.of(2005, 2, 12);
        System.out.println("Fecha de nacimiento: " + nacimiento);
        // Sumar días a una fecha
        LocalDate mañana = hoy.plusDays(1);
        System.out.println("Mañana será: " + mañana);
        // Comparar fechas
        if (hoy.isBefore(mañana)) {
            System.out.println("Hoy es antes del " + mañana);
        }
        // Crear una fecha a partir de una cadena de texto (String)
        LocalDate otraFecha = LocalDate.parse("2024-01-15");
        System.out.println("Otra fecha: " + otraFecha);
    }
}
Salida: (Ten en cuenta si ejecutas el código que las fechas de hoy y mañana diferirán)
Fecha actual: 2025-02-12
Fecha de nacimiento: 2005-02-12
Mañana será: 2025-02-13
Hoy es antes del 2025-02-13
Otra fecha: 2024-01-15
LocalDate.now()obtiene la fecha actual.LocalDate.of()crea una fecha específica.- LocalDate.parse(): Crea una fecha a partir de un texto. El formato por defecto es «AAAA-MM-DD».
 - Métodos como 
plusDays()eisBefore()facilitan la manipulación y comparación de fechas. 
2. LocalTime
Representa una hora sin información de fecha ni zona horaria, útil para horarios de apertura o cierre.
Ejemplo de uso:
import java.time.LocalTime;
public class EjemploLocalTime {
    public static void main(String[] args) {
        // Hora actual
        LocalTime ahora = LocalTime.now();
        System.out.println("Hora actual: " + ahora);
        // Crear una hora específica
        LocalTime inicioClase = LocalTime.of(8, 30);
        System.out.println("Inicio de clase: " + inicioClase);
        // Sumar horas y minutos
        LocalTime másTarde = ahora.plusHours(2).plusMinutes(15);
        System.out.println("En 2 horas y 15 minutos será: " + másTarde);
        // Crear una hora a partir de una cadena
        LocalTime otraHora = LocalTime.parse("14:45");
        System.out.println("Otra hora: " + otraHora);
    }
}
Salida:
Hora actual: 10:24:31.123
Inicio de clase: 08:30
En 2 horas y 15 minutos será: 12:39:31.123
Otra hora: 14:45
Explicación del código:
LocalTime.now()obtiene la hora actual.LocalTime.of()crea una hora específica.- Métodos como 
plusHours()permiten manipular la hora. LocalTime.parse(): Crea una hora a partir de un texto. El formato por defecto es «HH:MM».
3. LocalDateTime
Combina fecha y hora sin información de zona horaria. Útil para representar eventos específicos, registrar sucesos, etc.
Ejemplo de uso:
import java.time.LocalDateTime;
public class EjemploLocalDateTime {
    public static void main(String[] args) {
        // Fecha y hora actuales
        LocalDateTime ahora = LocalDateTime.now();
        System.out.println("Fecha y hora actuales: " + ahora);
        // Crear una fecha y hora específicas
        LocalDateTime evento = LocalDateTime.of(2025, 5, 20, 14, 0);
        System.out.println("Evento programado para: " + evento);
        // Restar días y horas
        LocalDateTime antes = evento.minusDays(2).minusHours(3);
        System.out.println("Dos días y tres horas antes del evento: " + antes);
        // Crear a partir de cadenas
        LocalDateTime otraFechaHora = LocalDateTime.parse("2024-03-10T18:00");
        System.out.println("Otra fecha y hora: " + otraFechaHora);
    }
}
Salida:
Fecha y hora actuales: 2025-02-12T10:24:31.123
Evento programado para: 2025-05-20T14:00
Dos días y tres horas antes del evento: 2025-05-18T11:00
Otra fecha y hora: 2024-03-10T18:00
Explicación del código:
LocalDateTime.now()obtiene la fecha y hora actual.LocalDateTime.of()crea una fecha y hora específica.- Métodos como 
minusDays()yminusHours()permiten manipular la fecha y hora. - LocalDateTime.parse(«2024-03-10T18:00»): Crea una fecha y hora a partir de un texto. El formato por defecto es «AAAA-MM-DDTHH:MM». La «T» separa la fecha de la hora.
 
4. ZonedDateTime
Representa una fecha y hora con zona horaria, útil para aplicaciones globales, que manejan múltiples zonas horarias.
Ejemplo de uso:
import java.time.ZonedDateTime;
import java.time.ZoneId;
public class EjemploZonedDateTime {
    public static void main(String[] args) {
        // Fecha y hora actuales en la zona horaria del sistema
        ZonedDateTime ahora = ZonedDateTime.now();
        System.out.println("Fecha y hora actuales: " + ahora);
        // Crear una fecha y hora específica con zona horaria
        ZonedDateTime fechaHoraEspecifica = ZonedDateTime.of(2025, 2, 13, 14, 30, 0, 0, ZoneId.of("Europe/Madrid"));
        System.out.println("Fecha y hora específica con zona horaria: " + fechaHoraEspecifica);
        // Cambiar la zona horaria
        ZonedDateTime fechaHoraNuevaZona = fechaHoraEspecifica.withZoneSameInstant(ZoneId.of("America/New_York"));
        System.out.println("Fecha y hora en Nueva York: " + fechaHoraNuevaZona);
        //Crear una fecha desde un string
        ZonedDateTime otraFechaConZona = ZonedDateTime.parse("2025-02-13T10:21:21.978+01:00[Europe/Paris]");
        System.out.println("Otra fecha con zona horaria: " + otraFechaConZona);
    }
}
Salida:
Fecha y hora actuales: 2025-02-13T10:21:21.978+01:00[Europe/Paris]
Fecha y hora específica con zona horaria: 2025-02-13T14:30+01:00[Europe/Madrid]
Fecha y hora en Nueva York: 2025-02-13T08:30-05:00[America/New_York]
Otra fecha con zona horaria: 2025-02-13T10:21:21.978+01:00[Europe/Paris]
Explicación del código:
- Necesitamos ZoneId para especificar la zona horaria. ZoneId.of(«Europe/Madrid») crea un objeto que representa la zona horaria de Madrid.
 ZonedDateTime.now()obtiene la fecha y hora actual con la zona horaria del sistema.ZonedDateTime.of()crea una fecha y hora específica con una zona horaria.withZoneSameInstant()convierte la fecha y hora a otra zona horaria.ZonedDateTime.parse(): Permite la creación desde texto especificando la zona horaria.
Desmenuzando el tiempo: obteniendo información
Una vez que tienes una fecha, puedes extraer información útil:
import java.time.LocalDate;
import java.time.Month;
public class ObtenerInfo {
    public static void main(String[] args) {
        LocalDate miCumple = LocalDate.of(2006, 5, 10);
        int anio = miCumple.getYear();
        Month mes = miCumple.getMonth();
        int dia = miCumple.getDayOfMonth();
        int diaDelAnio = miCumple.getDayOfYear();
        System.out.println("Año: " + anio); // Año: 2006
        System.out.println("Mes: " + mes);   // Mes: MAY
        System.out.println("Día: " + dia);   // Día: 10
        System.out.println("Día del año: " + diaDelAnio); // Día del año: 130 (El día 130 del año)
    }
}
Explicación:
getYear(): Obtiene el año.getMonth(): Obtiene el mes (como un objeto Month).getDayOfMonth(): Obtiene el día del mes.getDayOfYear(): Obtiene el día del año (1-365/366).
Formateo y Análisis de Fechas
El formateo de fechas es esencial para mostrar fechas en un formato legible para el usuario. La clase DateTimeFormatter permite definir patrones personalizados para formatear y parsear fechas (interpretar fechas en formato String).
Patrones Comunes
| Símbolo | Significado | Ejemplo | 
|---|---|---|
yyyy | Año con 4 dígitos | 2023 | 
MM | Mes con 2 dígitos | 10 (octubre) | 
dd | Día con 2 dígitos | 15 | 
HH | Hora (24 horas) | 14 | 
mm | Minutos | 30 | 
ss | Segundos | 45 | 
EEE | Día de la semana | Mon (lunes) | 
MMMM | Mes completo | October | 
Ejemplo de formateo:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class FormateoFechas {
    public static void main(String[] args) {
        LocalDate fecha = LocalDate.of(2023, 10, 15);
        // Formatear fecha en "dd/MM/yyyy"
        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        System.out.println("Fecha formateada (dd/MM/yyyy): " + fecha.format(formatter1));
        // Formatear fecha en "MMMM dd, yyyy"
        DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("MMMM dd, yyyy");
        System.out.println("Fecha formateada (MMMM dd, yyyy): " + fecha.format(formatter2));
        // Formatear fecha en "EEE, dd MMM yyyy"
        DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy");
        System.out.println("Fecha formateada (EEE, dd MMM yyyy): " + fecha.format(formatter3));
    }
}
Salida:
Fecha formateada (dd/MM/yyyy): 15/10/2023
Fecha formateada (MMMM dd, yyyy): October 15, 2023
Fecha formateada (EEE, dd MMM yyyy): Sun, 15 Oct 2023
Ejemplo de análisis:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class EjemploAnalisis {
    public static void main(String[] args) {
        String fechaTexto = "15/08/2025";
        DateTimeFormatter formato = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        LocalDate fecha = LocalDate.parse(fechaTexto, formato);
        System.out.println("Fecha analizada: " + fecha);
    }
}
Salida:
Fecha analizada: 2025-08-15
Modificación de fechas
Las clases de java.time proporcionan métodos para modificar fechas de manera sencilla. Estos métodos devuelven un nuevo objeto, ya que las fechas son inmutables.
Métodos Comunes
| Método | Descripción | Ejemplo | 
|---|---|---|
plusDays(long) | Suma días a la fecha | fecha.plusDays(5) | 
minusDays(long) | Resta días a la fecha | fecha.minusDays(5) | 
plusMonths(long) | Suma meses a la fecha | fecha.plusMonths(2) | 
minusMonths(long) | Resta meses a la fecha | fecha.minusMonths(2) | 
plusYears(long) | Suma años a la fecha | fecha.plusYears(1) | 
minusYears(long) | Resta años a la fecha | fecha.minusYears(1) | 
withDayOfMonth(int) | Cambia el día del mes | fecha.withDayOfMonth(20) | 
withMonth(int) | Cambia el mes | fecha.withMonth(12) | 
withYear(int) | Cambia el año | fecha.withYear(2024) | 
Ejemplo de Modificación
import java.time.LocalDate;
public class ModificacionFechas {
    public static void main(String[] args) {
        LocalDate fecha = LocalDate.of(2023, 10, 15);
        // Sumar 5 días
        LocalDate fechaSumada = fecha.plusDays(5);
        System.out.println("Fecha + 5 días: " + fechaSumada);
        // Restar 2 meses
        LocalDate fechaRestada = fecha.minusMonths(2);
        System.out.println("Fecha - 2 meses: " + fechaRestada);
        // Cambiar el año a 2024
        LocalDate fechaCambiada = fecha.withYear(2024);
        System.out.println("Fecha con año 2024: " + fechaCambiada);
    }
}
Salida:
Fecha + 5 días: 2023-10-20
Fecha - 2 meses: 2023-08-15
Fecha con año 2024: 2024-10-15
Comparación entre Fechas
Comparar fechas es una operación común para determinar si una fecha es anterior, posterior o igual a otra.
Métodos Comunes
| Método | Descripción | Ejemplo | 
|---|---|---|
isBefore() | Verifica si una fecha es anterior | fecha1.isBefore(fecha2) | 
isAfter() | Verifica si una fecha es posterior | fecha1.isAfter(fecha2) | 
isEqual() | Verifica si dos fechas son iguales | fecha1.isEqual(fecha2) | 
compareTo() | Compara dos fechas (devuelve -1, 0, 1) | fecha1.compareTo(fecha2) | 
Ejemplo de Comparación
import java.time.LocalDate;
public class ComparacionFechas {
    public static void main(String[] args) {
        LocalDate fecha1 = LocalDate.of(2023, 10, 15);
        LocalDate fecha2 = LocalDate.of(2023, 12, 25);
        // Verificar si fecha1 es antes que fecha2
        if (fecha1.isBefore(fecha2)) {
            System.out.println("fecha1 es antes que fecha2");
        }
        // Verificar si fecha1 es después que fecha2
        if (fecha1.isAfter(fecha2)) {
            System.out.println("fecha1 es después que fecha2");
        }
        // Verificar si fecha1 es igual a fecha2
        if (fecha1.isEqual(fecha2)) {
            System.out.println("fecha1 es igual a fecha2");
        }
        // Comparar fechas usando compareTo
        int comparacion = fecha1.compareTo(fecha2);
        if (comparacion < 0) {
            System.out.println("fecha1 es anterior a fecha2");
        } else if (comparacion > 0) {
            System.out.println("fecha1 es posterior a fecha2");
        } else {
            System.out.println("fecha1 es igual a fecha2");
        }
    }
}
Salida:
fecha1 es antes que fecha2
fecha1 es anterior a fecha2
Conclusión
La API java.time de Java 1.8 es la mejor forma de manejar fechas y horas en Java. Es moderna, intuitiva y sigue estándares internacionales. Permite crear fechas de distintas maneras, con y sin zona horaria. También el formateo, modificación y comparación de fechas, que son operaciones esenciales en cualquier aplicación. 
Con la API java.time de Java 1.8, estas tareas son más sencillas y seguras. Con estas herramientas, podrás trabajar con fechas de manera eficiente y sin errores comunes. ¡Practica con los ejemplos y domina esta API!
Próximos Pasos
- Experimenta con los ejemplos de esta guía.
 - Investiga otros métodos de las clases LocalDate, LocalTime, LocalDateTime y ZonedDateTime.
 - Practica el formateo de fechas con diferentes patrones.
 - Explora cómo convertir entre la antigua API java.util.Date y la nueva java.time (si necesitas trabajar con código antiguo).
 


Deja una respuesta