Fechas y tiempo
Guardar "08/10/2026" como texto no aclara el orden, no impide fechas imposibles y dificulta calcular. java.time aporta tipos con significado.
LocalDate: una fecha
Representa año, mes y día, sin hora ni zona:
LocalDate hoy = LocalDate.now();
LocalDate entrega = LocalDate.of(2026, 10, 20);
LocalDate siguiente = entrega.plusDays(7);
LocalDate anterior = entrega.minusMonths(1);
System.out.println(hoy.isBefore(entrega));
System.out.println(entrega.isAfter(anterior));
System.out.println(entrega.compareTo(siguiente));
Los objetos son inmutables: plusDays devuelve otra fecha.
Parsear y formatear
El formato ISO yyyy-MM-dd funciona directamente:
LocalDate fecha = LocalDate.parse("2026-10-08");
Para validar una entrada con el formato día, mes y año, declaramos un patrón estricto:
DateTimeFormatter formato = DateTimeFormatter
.ofPattern("dd/MM/uuuu")
.withResolverStyle(ResolverStyle.STRICT);
LocalDate fecha = LocalDate.parse("08/10/2026", formato);
System.out.println(fecha.format(formato));
uuuu representa el año de forma adecuada para este parseo estricto. ResolverStyle.STRICT hace que una fecha imposible, como 31/02/2026, provoque DateTimeParseException; puede capturarse en el límite de entrada para pedir una fecha correcta.
Period: distancia entre fechas
Period trabaja con años, meses y días del calendario:
LocalDate nacimiento = LocalDate.of(2000, 5, 10);
Period edad = Period.between(nacimiento, LocalDate.of(2026, 10, 8));
System.out.println(edad.getYears());
Para días totales entre fechas puede usarse ChronoUnit.DAYS.between(inicio, fin).
LocalDateTime y Duration
LocalDateTime representa fecha y hora, pero no zona horaria. Duration mide tiempo en segundos y nanosegundos, apropiado para sesiones:
LocalDateTime inicio = LocalDateTime.of(2026, 10, 8, 10, 0);
LocalDateTime fin = inicio.plusMinutes(95);
Duration duracion = Duration.between(inicio, fin);
System.out.println(duracion.toMinutes());
Usa Period para cantidades de calendario y Duration para tiempo transcurrido. Zonas horarias, Instant y APIs antiguas como Date/Calendar quedan fuera del flujo principal.
Ejemplo completo
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.time.format.ResolverStyle;
public class FechasDemo {
public static void main(String[] args) {
DateTimeFormatter formato = DateTimeFormatter
.ofPattern("dd/MM/uuuu")
.withResolverStyle(ResolverStyle.STRICT);
LocalDate alta = LocalDate.parse("08/10/2024", formato);
LocalDate revision = alta.plusYears(2);
Period antiguedad = Period.between(alta, revision);
LocalDateTime inicio = LocalDateTime.of(2026, 10, 8, 9, 30);
Duration sesion = Duration.between(inicio, inicio.plusMinutes(75));
System.out.println(revision.format(formato));
System.out.println(antiguedad.getYears());
System.out.println(sesion.toMinutes());
}
}
Errores habituales
- Usar
Stringcomo modelo de fecha. - Confundir
MM(mes) conmm(minuto). - Ignorar que
LocalDateTimeno contiene zona. - Usar
Durationpara una edad en años oPeriodpara segundos. - Esperar que
plusDaysmodifique el objeto original.
Practica: vencimiento
Enunciado y criterios
Parsea una fecha dd/MM/uuuu, suma 30 días y determina si vence antes de una fecha de referencia. Muestra el resultado con el mismo formato.
Solución
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.ResolverStyle;
public class VencimientoDemo {
public static void main(String[] args) {
DateTimeFormatter formato = DateTimeFormatter
.ofPattern("dd/MM/uuuu")
.withResolverStyle(ResolverStyle.STRICT);
LocalDate inicio = LocalDate.parse("01/10/2026", formato);
LocalDate vencimiento = inicio.plusDays(30);
LocalDate referencia = LocalDate.of(2026, 11, 5);
System.out.println(vencimiento.format(formato));
System.out.println(vencimiento.isBefore(referencia));
}
}
El tipo impide fechas imposibles y ofrece operaciones que expresan la intención.