Saltar al contenido principal

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 String como modelo de fecha.
  • Confundir MM (mes) con mm (minuto).
  • Ignorar que LocalDateTime no contiene zona.
  • Usar Duration para una edad en años o Period para segundos.
  • Esperar que plusDays modifique 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.