1. Suma y resta de fechas y horas
En programación, trabajar con fechas y horas no es solo «mostrar la fecha bonita en pantalla». Muy a menudo se necesita:
- saber cuántos días quedan hasta un evento importante;
- calcular la edad de un usuario;
- determinar cuánto tiempo ha pasado entre dos eventos;
- comprobar si ya ha llegado la fecha límite;
- sumar a una fecha una cantidad determinada de días, semanas, meses u horas.
Por ejemplo, en nuestra aplicación queremos recordar al usuario que quedan 3 días hasta la fecha límite de una tarea. O felicitarle por su cumpleaños pasado (si la fecha ya quedó en el pasado).
Para ello, en java.time hay clases y métodos especiales que hacen estos cálculos de forma sencilla y segura.
Métodos principales para sumar y restar
Todas las clases de fecha y hora (LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant) tienen métodos:
- plusXxx() — sumar (días, meses, años, horas, minutos, etc.)
- minusXxx() — restar (lo mismo)
import java.time.LocalDate;
LocalDate today = LocalDate.now(); // Fecha de hoy
LocalDate tomorrow = today.plusDays(1); // Mañana
LocalDate nextMonth = today.plusMonths(1); // Dentro de un mes
LocalDate lastWeek = today.minusWeeks(1); // Hace una semana
System.out.println("Hoy: " + today);
System.out.println("Mañana: " + tomorrow);
System.out.println("Dentro de un mes: " + nextMonth);
System.out.println("Hace una semana: " + lastWeek);
Todos estos métodos devuelven un nuevo objeto y no modifican el original. ¡La inmutabilidad lo es todo!
import java.time.LocalTime;
LocalTime now = LocalTime.now();
LocalTime inTwoHours = now.plusHours(2);
LocalTime tenMinutesAgo = now.minusMinutes(10);
System.out.println("Ahora: " + now);
System.out.println("Dentro de 2 horas: " + inTwoHours);
System.out.println("Hace 10 minutos: " + tenMinutesAgo);
Métodos combinados
LocalDate vacation = today.plusMonths(2).plusDays(10);
System.out.println("Vacaciones: " + vacation);
2. Obtener la diferencia entre fechas: Period y Duration
Cuando hay que saber cuánto tiempo pasó entre dos fechas o momentos, entran en escena dos protagonistas — Period y Duration. Conozcámoslos más de cerca.
¿Cuál es la diferencia entre Period y Duration?
- Period — para trabajar con fechas (año, mes, día). Por ejemplo, «3 años, 2 meses y 5 días».
- Duration — para trabajar con tiempo (horas, minutos, segundos, nanosegundos). Por ejemplo, «5 horas 30 minutos».
| Clase | Para qué sirve | Ejemplo de uso |
|---|---|---|
|
Diferencia entre fechas | Cuántos años/meses/días hay entre fechas |
|
Diferencia entre instantes | Cuántas horas/minutos/segundos hay entre eventos |
Ejemplo: calcular la edad de un usuario
import java.time.LocalDate;
import java.time.Period;
LocalDate birthday = LocalDate.of(2000, 1, 15); // Fecha de nacimiento
LocalDate today = LocalDate.now();
Period age = Period.between(birthday, today);
System.out.println("Edad: " + age.getYears() + " años, " +
age.getMonths() + " meses, " +
age.getDays() + " días");
Analogía: Period es como la diferencia «humana» entre fechas («tengo 24 años 5 meses 12 días»).
Ejemplo: cuánto tiempo queda hasta la fecha límite
import java.time.LocalDate;
LocalDate deadline = LocalDate.of(2025, 7, 1);
LocalDate today = LocalDate.now();
if (today.isBefore(deadline)) {
Period left = Period.between(today, deadline);
System.out.println("Hasta la fecha límite queda: " +
left.getMonths() + " meses y " +
left.getDays() + " días");
} else {
System.out.println("¡La fecha límite ya ha pasado!");
}
Duration: diferencia en el tiempo
import java.time.LocalDateTime;
import java.time.Duration;
LocalDateTime start = LocalDateTime.of(2025, 6, 1, 10, 0, 0);
LocalDateTime end = LocalDateTime.of(2025, 6, 1, 15, 30, 0);
Duration duration = Duration.between(start, end);
System.out.println("Duración: " + duration.toHours() + " horas " +
(duration.toMinutes() % 60) + " minutos");
Duration mide la diferencia en segundos, minutos, horas, días (pero los días son siempre de 24 horas, sin tener en cuenta particularidades del calendario).
Comparación: ¿cuándo usar Period y cuándo Duration?
- Si solo tienes fechas (sin hora), usa Period.
- Si hay hora (por ejemplo, LocalDateTime, Instant), usa Duration.
3. Comparación de fechas y horas: isBefore, isAfter, equals
A veces solo necesitas entender: ¿la fecha ya ha llegado o aún no? ¿El evento está en el pasado o en el futuro? Para ello, todas las clases de fecha y hora tienen métodos:
- isBefore(otraFecha)
- isAfter(otraFecha)
- isEqual(otraFecha) (o simplemente equals)
import java.time.LocalDate;
LocalDate today = LocalDate.now();
LocalDate deadline = LocalDate.of(2025, 7, 1);
if (today.isBefore(deadline)) {
System.out.println("¡Aún hay tiempo!");
} else if (today.isEqual(deadline)) {
System.out.println("¡Hoy es la fecha límite!");
} else {
System.out.println("La fecha límite ya ha pasado :(");
}
import java.time.LocalTime;
LocalTime now = LocalTime.now();
LocalTime lunch = LocalTime.of(13, 0);
if (now.isAfter(lunch)) {
System.out.println("¡La comida ya ha pasado!");
} else {
System.out.println("Todavía queda tiempo hasta la comida.");
}
Importante: solo se pueden comparar objetos del mismo tipo (LocalDate con LocalDate, LocalDateTime con LocalDateTime, etc.).
4. Práctica: ejercicios de cálculo de diferencias y comprobación de plazos
Ejemplo: cuántos días quedan hasta la fecha límite de una tarea
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
LocalDate today = LocalDate.now();
LocalDate deadline = LocalDate.of(2025, 7, 1);
long daysLeft = ChronoUnit.DAYS.between(today, deadline);
if (daysLeft > 0) {
System.out.println("Hasta la fecha límite quedan " + daysLeft + " días");
} else if (daysLeft == 0) {
System.out.println("¡Hoy es la fecha límite!");
} else {
System.out.println("La fecha límite fue hace " + Math.abs(daysLeft) + " días");
}
ChronoUnit.DAYS.between() es una forma práctica de saber la cantidad exacta de días entre dos fechas (sin tener en cuenta meses y años).
Ejemplo: cuántos segundos hay entre dos eventos
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
LocalDateTime start = LocalDateTime.of(2025, 6, 1, 10, 0, 0);
LocalDateTime end = LocalDateTime.of(2025, 6, 1, 15, 30, 0);
long seconds = ChronoUnit.SECONDS.between(start, end);
System.out.println("Entre los eventos han pasado " + seconds + " segundos");
Ejemplo: calcular la antigüedad de una tarea
import java.time.LocalDate;
import java.time.Period;
LocalDate created = LocalDate.of(2025, 5, 20);
LocalDate today = LocalDate.now();
Period period = Period.between(created, today);
System.out.println("La tarea se creó hace " +
period.getDays() + " días, " +
period.getMonths() + " meses y " +
period.getYears() + " años.");
Ejemplo: duración entre dos Instant
import java.time.Instant;
import java.time.Duration;
Instant start = Instant.now();
// ... hacemos algo ...
Instant end = Instant.now();
Duration duration = Duration.between(start, end);
System.out.println("La ejecución tardó " + duration.toMillis() + " milisegundos");
5. Particularidades del uso de Period y Duration
Particularidades de Period
- Period calcula la diferencia según el calendario: entre el 28 de febrero y el 1 de marzo — 1 día, aunque sean meses distintos.
- Se puede obtener la cantidad de años, meses y días por separado: getYears(), getMonths(), getDays().
- Si necesitas saber la cantidad total de días entre fechas, usa ChronoUnit.DAYS.between().
Particularidades de Duration
- Duration trabaja con tiempo exacto (horas, minutos, segundos).
- Puede trabajar con LocalTime, LocalDateTime, Instant.
- No se puede usar para fechas sin hora (LocalDate): lanzará una excepción.
Ejemplo: diferencia entre Period y Duration
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Duration;
import java.time.Period;
LocalDate date1 = LocalDate.of(2025, 2, 28);
LocalDate date2 = LocalDate.of(2025, 3, 1);
Period period = Period.between(date1, date2); // 2 días (año bisiesto)
long days = java.time.temporal.ChronoUnit.DAYS.between(date1, date2); // 2 días
System.out.println("Period: " + period.getDays() + " días");
System.out.println("ChronoUnit: " + days + " días");
LocalDateTime dt1 = LocalDateTime.of(2025, 6, 1, 23, 0);
LocalDateTime dt2 = LocalDateTime.of(2025, 6, 2, 1, 0);
Duration duration = Duration.between(dt1, dt2); // 2 horas
System.out.println("Duration: " + duration.toHours() + " horas");
6. Uso de Duration y Period para mostrar la diferencia en un formato cómodo
Cuando calculas la diferencia entre fechas u horas para el usuario, no siempre es útil mostrar «123456 segundos». Normalmente se quiere algo como «2 días 3 horas 15 minutos».
Ejemplo: mostrar la diferencia entre fechas y horas
import java.time.LocalDateTime;
import java.time.Duration;
LocalDateTime start = LocalDateTime.of(2025, 6, 1, 14, 0);
LocalDateTime end = LocalDateTime.of(2025, 6, 3, 16, 30);
Duration duration = Duration.between(start, end);
long days = duration.toDays();
long hours = duration.minusDays(days).toHours();
long minutes = duration.minusDays(days).minusHours(hours).toMinutes();
System.out.println("Diferencia: " + days + " días " +
hours + " horas " + minutes + " minutos");
7. Particularidades al trabajar con ZonedDateTime e Instant
- La diferencia entre dos ZonedDateTime en zonas distintas se calcula según el tiempo absoluto, no según el tiempo «humano» en cada zona.
- El cambio de horario de verano/invierno puede influir en la diferencia en horas entre fechas.
Ejemplo: diferencia entre ZonedDateTime
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.Duration;
ZonedDateTime MinskTime = ZonedDateTime.of(2025, 6, 1, 12, 0, 0, 0, ZoneId.of("Europe/Minsk"));
ZonedDateTime nyTime = ZonedDateTime.of(2025, 6, 1, 5, 0, 0, 0, ZoneId.of("America/New_York"));
Duration diff = Duration.between(nyTime, MinskTime);
System.out.println("Diferencia: " + diff.toHours() + " horas");
8. Errores típicos al hacer cálculos con fechas y horas
Error n.º 1: confundir Period y Duration.
Si intentas usar Duration para LocalDate, obtendrás una excepción. Para fechas usa Period, para el tiempo — Duration.
Error n.º 2: no tener en cuenta los husos horarios.
Si comparas fechas y horas en diferentes husos horarios, puedes obtener resultados inesperados. Es mejor unificar todo a un mismo huso o usar Instant.
Error n.º 3: esperar que los métodos plus/minus modifiquen el objeto.
¡Todos los objetos de java.time son inmutables! No olvides asignar el resultado a una variable nueva (por ejemplo, today = today.plusDays(1)).
Error n.º 4: usar getDays() de Period y pensar que es el total de días.
En realidad, son solo los días residuales tras restar años y meses. Para el total de días usa ChronoUnit.DAYS.between().
Error n.º 5: comparar objetos de tipos distintos.
Los métodos isBefore, isAfter, isEqual solo funcionan para objetos del mismo tipo (por ejemplo, LocalDate con LocalDate).
GO TO FULL VERSION