Java

Tutorial Java: LocalTime

Aprende a usar Java LocalTime para manipular horas, realizar cálculos temporales y formatear tiempos con ejemplos prácticos y avanzados.

Aprende Java y certifícate

Creación y manipulación básica de tiempo sin fecha

La clase LocalTime forma parte del paquete java.time introducido en Java 8, y está diseñada específicamente para representar y manipular horas sin componente de fecha. Esta clase es inmutable y thread-safe, lo que la hace ideal para aplicaciones concurrentes.

A diferencia de las antiguas clases para manejo de tiempo como java.util.Date, LocalTime se centra exclusivamente en representar un momento del día, como "10:30:45", sin información sobre el día, mes o año.

Creación de objetos LocalTime

Existen varias formas de crear instancias de LocalTime:

  • 1. Obtener la hora actual del sistema:
// Obtiene la hora actual del sistema
LocalTime ahora = LocalTime.now();
System.out.println("Hora actual: " + ahora);
  • 2. Crear una hora específica mediante valores de hora, minuto, segundo y nanosegundo:
// Hora y minutos
LocalTime desayuno = LocalTime.of(8, 30);

// Hora, minutos y segundos
LocalTime almuerzo = LocalTime.of(13, 0, 0);

// Hora, minutos, segundos y nanosegundos
LocalTime cena = LocalTime.of(21, 0, 0, 0);

System.out.println("Desayuno: " + desayuno);
System.out.println("Almuerzo: " + almuerzo);
System.out.println("Cena: " + cena);
  • 3. Parsear una cadena de texto que represente una hora:
// Formato ISO-8601 (HH:mm:ss)
LocalTime hora1 = LocalTime.parse("15:30:45");

// Con un formateador personalizado
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH mm ss");
LocalTime hora2 = LocalTime.parse("20 30 00", formatter);

System.out.println("Hora parseada 1: " + hora1);
System.out.println("Hora parseada 2: " + hora2);
  • 4. Obtener horas predefinidas:
// Hora mínima (00:00)
LocalTime minima = LocalTime.MIN;

// Hora máxima (23:59:59.999999999)
LocalTime maxima = LocalTime.MAX;

// Mediodía (12:00)
LocalTime mediodia = LocalTime.NOON;

// Medianoche (00:00)
LocalTime medianoche = LocalTime.MIDNIGHT;

System.out.println("Hora mínima: " + minima);
System.out.println("Hora máxima: " + maxima);
System.out.println("Mediodía: " + mediodia);
System.out.println("Medianoche: " + medianoche);

Acceso a componentes de tiempo

Podemos extraer los diferentes componentes de un objeto LocalTime:

LocalTime tiempo = LocalTime.of(13, 45, 30, 123456789);

int hora = tiempo.getHour();         // 13
int minuto = tiempo.getMinute();     // 45
int segundo = tiempo.getSecond();    // 30
int nano = tiempo.getNano();         // 123456789

System.out.println("Hora: " + hora);
System.out.println("Minuto: " + minuto);
System.out.println("Segundo: " + segundo);
System.out.println("Nanosegundo: " + nano);

Manipulación básica de tiempo

Como LocalTime es inmutable, cualquier operación de modificación devuelve una nueva instancia sin alterar la original:

  • 1. Añadir o restar unidades de tiempo:
LocalTime ahora = LocalTime.of(15, 30);

// Añadir horas, minutos, segundos o nanosegundos
LocalTime masTarde = ahora.plusHours(2);
LocalTime masMinutos = ahora.plusMinutes(15);
LocalTime masSegundos = ahora.plusSeconds(30);
LocalTime masNanos = ahora.plusNanos(1000000);

// Restar unidades de tiempo
LocalTime masAntes = ahora.minusHours(1);
LocalTime menosMinutos = ahora.minusMinutes(10);

System.out.println("Hora original: " + ahora);
System.out.println("Dos horas más tarde: " + masTarde);
System.out.println("15 minutos más tarde: " + masMinutos);
System.out.println("Una hora antes: " + masAntes);
  • 2. Modificar componentes específicos:
LocalTime tiempo = LocalTime.of(16, 30, 20);

// Cambiar componentes individuales
LocalTime nuevaHora = tiempo.withHour(20);
LocalTime nuevoMinuto = tiempo.withMinute(45);
LocalTime nuevoSegundo = tiempo.withSecond(0);
LocalTime nuevoNano = tiempo.withNano(0);

System.out.println("Tiempo original: " + tiempo);
System.out.println("Con hora cambiada: " + nuevaHora);
System.out.println("Con minuto cambiado: " + nuevoMinuto);
  • 3. Truncar a una unidad específica:
LocalTime detallado = LocalTime.of(12, 34, 56, 789000000);

// Truncar a diferentes unidades
LocalTime soloHora = detallado.truncatedTo(ChronoUnit.HOURS);       // 12:00
LocalTime hastaMinutos = detallado.truncatedTo(ChronoUnit.MINUTES); // 12:34
LocalTime hastaSegundos = detallado.truncatedTo(ChronoUnit.SECONDS); // 12:34:56

System.out.println("Tiempo original: " + detallado);
System.out.println("Truncado a horas: " + soloHora);
System.out.println("Truncado a minutos: " + hastaMinutos);
System.out.println("Truncado a segundos: " + hastaSegundos);

Consultas sobre el tiempo

LocalTime proporciona métodos para realizar consultas sobre el valor del tiempo:

LocalTime tiempo = LocalTime.of(14, 30);

// Comprobar si un tiempo está antes o después de otro
boolean esAntes = tiempo.isBefore(LocalTime.of(15, 0));  // true
boolean esDespues = tiempo.isAfter(LocalTime.NOON);      // true

// Comprobar si es mediodía o medianoche
boolean esMediodia = tiempo.equals(LocalTime.NOON);      // false
boolean esMedianoche = tiempo.equals(LocalTime.MIDNIGHT); // false

System.out.println("¿14:30 es antes de las 15:00? " + esAntes);
System.out.println("¿14:30 es después del mediodía? " + esDespues);

Ejemplo práctico: Control de horarios

Un ejemplo práctico de uso de LocalTime podría ser un sistema de control de horarios laborales:

public class ControlHorario {
    public static void main(String[] args) {
        // Definir horarios laborales
        LocalTime inicioJornada = LocalTime.of(9, 0);
        LocalTime finJornada = LocalTime.of(18, 0);
        LocalTime inicioDescanso = LocalTime.of(13, 0);
        LocalTime finDescanso = LocalTime.of(14, 0);
        
        // Registrar entrada de un empleado
        LocalTime horaEntrada = LocalTime.of(8, 45);
        
        // Comprobar si ha llegado a tiempo
        if (horaEntrada.isAfter(inicioJornada)) {
            System.out.println("Empleado ha llegado tarde");
            
            // Calcular minutos de retraso
            long minutosRetraso = ChronoUnit.MINUTES.between(inicioJornada, horaEntrada);
            System.out.println("Minutos de retraso: " + minutosRetraso);
        } else {
            System.out.println("Empleado ha llegado a tiempo");
            
            // Calcular minutos de antelación
            long minutosAntelacion = ChronoUnit.MINUTES.between(horaEntrada, inicioJornada);
            System.out.println("Minutos de antelación: " + minutosAntelacion);
        }
        
        // Comprobar si una hora está dentro del horario laboral (excluyendo descanso)
        LocalTime horaConsulta = LocalTime.of(15, 30);
        boolean enHorarioLaboral = (horaConsulta.isAfter(inicioJornada) && horaConsulta.isBefore(finJornada)) 
                                && !(horaConsulta.isAfter(inicioDescanso) && horaConsulta.isBefore(finDescanso));
        
        System.out.println("¿Está en horario laboral? " + enHorarioLaboral);
    }
}

Este ejemplo muestra cómo LocalTime puede utilizarse para gestionar horarios y calcular diferencias de tiempo, sin preocuparse por componentes de fecha.

Cálculos, comparación y operaciones con LocalTime

La clase LocalTime no solo nos permite representar momentos del día, sino que también ofrece un conjunto completo de operaciones para realizar cálculos temporales, comparaciones y otras manipulaciones avanzadas. Estas funcionalidades son fundamentales cuando necesitamos trabajar con horarios en aplicaciones como sistemas de reservas, planificadores o cualquier software que requiera lógica basada en horas.

Comparación entre instancias de LocalTime

Para determinar el orden cronológico entre dos horas, LocalTime proporciona varios métodos de comparación:

LocalTime primeraTarea = LocalTime.of(9, 30);
LocalTime segundaTarea = LocalTime.of(11, 15);
LocalTime terceraTarea = LocalTime.of(9, 30);

// Comparación con métodos específicos
boolean esAnterior = primeraTarea.isBefore(segundaTarea);  // true
boolean esPosterior = segundaTarea.isAfter(primeraTarea);  // true

// Comparación de igualdad
boolean sonIguales = primeraTarea.equals(terceraTarea);    // true

System.out.println("¿Primera tarea es anterior a segunda? " + esAnterior);
System.out.println("¿Segunda tarea es posterior a primera? " + esPosterior);
System.out.println("¿Primera y tercera tarea son a la misma hora? " + sonIguales);

También podemos utilizar el método compareTo() que devuelve un valor entero:

LocalTime hora1 = LocalTime.of(14, 30);
LocalTime hora2 = LocalTime.of(16, 45);

int resultado = hora1.compareTo(hora2);
// resultado < 0 significa que hora1 es anterior a hora2
// resultado = 0 significa que son iguales
// resultado > 0 significa que hora1 es posterior a hora2

String relacion = (resultado < 0) ? "anterior a" : 
                  (resultado > 0) ? "posterior a" : "igual a";

System.out.println("La hora " + hora1 + " es " + relacion + " la hora " + hora2);

Cálculo de periodos entre horas

Para calcular la duración entre dos instancias de LocalTime, podemos utilizar la clase ChronoUnit o la clase Duration:

  • Usando ChronoUnit para cálculos simples:
LocalTime inicio = LocalTime.of(8, 15);
LocalTime fin = LocalTime.of(10, 45);

// Calcular diferencia en distintas unidades
long diferenciaHoras = ChronoUnit.HOURS.between(inicio, fin);      // 2
long diferenciaMinutos = ChronoUnit.MINUTES.between(inicio, fin);  // 150
long diferenciaSegundos = ChronoUnit.SECONDS.between(inicio, fin); // 9000

System.out.println("Diferencia en horas: " + diferenciaHoras);
System.out.println("Diferencia en minutos: " + diferenciaMinutos);
System.out.println("Diferencia en segundos: " + diferenciaSegundos);
  • Usando Duration para cálculos más complejos:
LocalTime inicioClase = LocalTime.of(9, 0);
LocalTime finClase = LocalTime.of(10, 30);

// Crear un objeto Duration
Duration duracionClase = Duration.between(inicioClase, finClase);

// Extraer componentes de la duración
long horas = duracionClase.toHours();                      // 1
long minutos = duracionClase.toMinutes();                  // 90
long segundos = duracionClase.getSeconds();                // 5400
long minutosRestantes = duracionClase.toMinutesPart();     // 30

System.out.println("Duración de la clase: " + duracionClase);
System.out.println("Horas: " + horas);
System.out.println("Minutos totales: " + minutos);
System.out.println("Minutos (parte): " + minutosRestantes);

Manejo de horas que cruzan la medianoche

Un aspecto importante a considerar es que LocalTime representa un momento del día en un ciclo de 24 horas. Cuando calculamos duraciones que cruzan la medianoche, debemos tener cuidado:

LocalTime inicioTurno = LocalTime.of(22, 0);  // 10:00 PM
LocalTime finTurno = LocalTime.of(6, 0);      // 6:00 AM del día siguiente

// Cálculo incorrecto (resultado negativo)
long horasDirectas = ChronoUnit.HOURS.between(inicioTurno, finTurno);  // -16

// Solución: ajustar manualmente
long horasCorrectas = (horasDirectas < 0) ? horasDirectas + 24 : horasDirectas;  // 8

System.out.println("Horas de turno (cálculo directo): " + horasDirectas);
System.out.println("Horas de turno (corregido): " + horasCorrectas);

Una alternativa más robusta es utilizar LocalDateTime cuando necesitamos manejar periodos que cruzan la medianoche, pero si queremos mantenernos en el ámbito de LocalTime, podemos implementar esta lógica:

public static long horasEntreTiempos(LocalTime inicio, LocalTime fin) {
    if (fin.isBefore(inicio) || fin.equals(inicio)) {
        // Si fin es antes que inicio, asumimos que cruza la medianoche
        return ChronoUnit.HOURS.between(inicio, fin.plus(1, ChronoUnit.DAYS));
    } else {
        return ChronoUnit.HOURS.between(inicio, fin);
    }
}

Operaciones aritméticas con Duration

Podemos combinar LocalTime con Duration para realizar operaciones aritméticas más complejas:

LocalTime horaInicio = LocalTime.of(10, 15);

// Crear una duración
Duration duracion = Duration.ofHours(2).plusMinutes(30);  // 2 horas y 30 minutos

// Sumar la duración a la hora de inicio
LocalTime horaFin = horaInicio.plus(duracion);  // 12:45

// Restar una duración
LocalTime horaAnterior = horaInicio.minus(Duration.ofMinutes(45));  // 9:30

System.out.println("Hora de inicio: " + horaInicio);
System.out.println("Duración: " + duracion);
System.out.println("Hora de finalización: " + horaFin);
System.out.println("45 minutos antes de la hora de inicio: " + horaAnterior);

También podemos sumar y restar duraciones entre sí:

Duration primeraParte = Duration.ofMinutes(45);
Duration segundaParte = Duration.ofMinutes(30);

// Sumar duraciones
Duration total = primeraParte.plus(segundaParte);  // 1 hora y 15 minutos

// Multiplicar una duración
Duration doble = primeraParte.multipliedBy(2);     // 1 hora y 30 minutos

// Dividir una duración
Duration mitad = primeraParte.dividedBy(2);        // 22 minutos y 30 segundos

System.out.println("Duración total: " + total);
System.out.println("Duración doble: " + doble);
System.out.println("Duración mitad: " + mitad);

Ajustes temporales con TemporalAdjusters

Aunque los ajustadores temporales (TemporalAdjusters) son más comunes con fechas, también podemos crear ajustadores personalizados para LocalTime:

// Crear un ajustador que redondee al cuarto de hora más cercano
TemporalAdjuster redondearCuartoHora = temporal -> {
    LocalTime time = LocalTime.from(temporal);
    int minutes = time.getMinute();
    int mod = minutes % 15;
    
    if (mod < 8) {  // Redondear hacia abajo
        return time.minusMinutes(mod);
    } else {        // Redondear hacia arriba
        return time.plusMinutes(15 - mod);
    }
};

LocalTime ahora = LocalTime.of(14, 23);
LocalTime redondeado = ahora.with(redondearCuartoHora);  // 14:30

System.out.println("Hora original: " + ahora);
System.out.println("Redondeado al cuarto de hora: " + redondeado);

Ejemplo práctico: Planificador de citas

Veamos un ejemplo práctico de cómo utilizar estas operaciones para implementar un sencillo planificador de citas:

public class PlanificadorCitas {
    private LocalTime inicioJornada;
    private LocalTime finJornada;
    private Duration duracionCita;
    private List<LocalTime> citasReservadas;
    
    public PlanificadorCitas(LocalTime inicio, LocalTime fin, Duration duracionCita) {
        this.inicioJornada = inicio;
        this.finJornada = fin;
        this.duracionCita = duracionCita;
        this.citasReservadas = new ArrayList<>();
    }
    
    public List<LocalTime> obtenerHorariosDisponibles() {
        List<LocalTime> disponibles = new ArrayList<>();
        LocalTime horaActual = inicioJornada;
        
        while (horaActual.plus(duracionCita).isBefore(finJornada) || 
               horaActual.plus(duracionCita).equals(finJornada)) {
            
            if (estaDisponible(horaActual)) {
                disponibles.add(horaActual);
            }
            
            horaActual = horaActual.plusMinutes(30); // Intervalos de 30 minutos
        }
        
        return disponibles;
    }
    
    private boolean estaDisponible(LocalTime hora) {
        for (LocalTime citaReservada : citasReservadas) {
            LocalTime finCitaReservada = citaReservada.plus(duracionCita);
            
            // Verificar si hay solapamiento
            if (!(hora.isAfter(finCitaReservada) || 
                  hora.plus(duracionCita).isBefore(citaReservada) ||
                  hora.plus(duracionCita).equals(citaReservada))) {
                return false;
            }
        }
        return true;
    }
    
    public boolean reservarCita(LocalTime hora) {
        if (estaDisponible(hora)) {
            citasReservadas.add(hora);
            return true;
        }
        return false;
    }
    
    public static void main(String[] args) {
        // Crear un planificador para una jornada de 9:00 a 17:00 con citas de 1 hora
        PlanificadorCitas planificador = new PlanificadorCitas(
            LocalTime.of(9, 0),
            LocalTime.of(17, 0),
            Duration.ofHours(1)
        );
        
        // Reservar algunas citas
        planificador.reservarCita(LocalTime.of(10, 0));
        planificador.reservarCita(LocalTime.of(14, 0));
        
        // Obtener horarios disponibles
        List<LocalTime> disponibles = planificador.obtenerHorariosDisponibles();
        
        System.out.println("Horarios disponibles:");
        for (LocalTime hora : disponibles) {
            System.out.println(hora);
        }
    }
}

Este ejemplo muestra cómo podemos utilizar las operaciones de LocalTime junto con Duration para implementar un sistema que calcula los horarios disponibles para citas, teniendo en cuenta la duración de cada cita y evitando solapamientos.

Formateo e integración con otras clases de tiempo (Duration)

El manejo efectivo del tiempo en aplicaciones Java no solo implica realizar cálculos y comparaciones, sino también presentar la información temporal de manera adecuada y combinar LocalTime con otras clases del paquete java.time. En esta sección exploraremos cómo formatear objetos LocalTime para su visualización y cómo integrarlos con la clase Duration para operaciones más complejas.

Formateo de LocalTime

La clase DateTimeFormatter es la herramienta principal para convertir objetos temporales en cadenas de texto con el formato deseado. Ofrece gran flexibilidad para personalizar la representación de horas según las necesidades específicas de cada aplicación.

Formateadores predefinidos

Java proporciona varios formateadores estándar que podemos utilizar directamente:

LocalTime ahora = LocalTime.of(14, 30, 45);

// Formatos ISO predefinidos
String formatoISO = ahora.format(DateTimeFormatter.ISO_LOCAL_TIME);  // "14:30:45"
String formatoBasico = ahora.format(DateTimeFormatter.ISO_TIME);     // "14:30:45"

System.out.println("Formato ISO: " + formatoISO);
System.out.println("Formato ISO básico: " + formatoBasico);

Patrones de formato personalizados

Para casos más específicos, podemos crear formateadores con patrones personalizados:

LocalTime tiempo = LocalTime.of(18, 45, 30, 123456789);

// Crear formateadores con patrones personalizados
DateTimeFormatter formato12h = DateTimeFormatter.ofPattern("hh:mm:ss a");  // Formato 12 horas con AM/PM
DateTimeFormatter formatoCorto = DateTimeFormatter.ofPattern("HH:mm");     // Solo hora y minutos
DateTimeFormatter formatoDetallado = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");  // Con milisegundos

// Aplicar los formateadores
String tiempo12h = tiempo.format(formato12h);           // "06:45:30 PM"
String tiempoCorto = tiempo.format(formatoCorto);       // "18:45"
String tiempoDetallado = tiempo.format(formatoDetallado); // "18:45:30.123"

System.out.println("Formato 12 horas: " + tiempo12h);
System.out.println("Formato corto: " + tiempoCorto);
System.out.println("Formato con milisegundos: " + tiempoDetallado);

Los patrones de formato más comunes para LocalTime incluyen:

  • HH - Hora en formato 24 horas (00-23)
  • hh - Hora en formato 12 horas (01-12)
  • mm - Minutos (00-59)
  • ss - Segundos (00-59)
  • a - Marcador AM/PM
  • SSS - Milisegundos (000-999)
  • n - Nanosegundos

Formateadores con configuración regional (Locale)

Para adaptar el formato a diferentes idiomas y convenciones regionales:

LocalTime medioDia = LocalTime.of(12, 0);

// Formateadores con diferentes configuraciones regionales
DateTimeFormatter formateadorES = DateTimeFormatter.ofPattern("hh:mm a")
                                                  .withLocale(new Locale("es", "ES"));
DateTimeFormatter formateadorUS = DateTimeFormatter.ofPattern("hh:mm a")
                                                  .withLocale(Locale.US);
DateTimeFormatter formateadorFR = DateTimeFormatter.ofPattern("HH'h'mm")
                                                  .withLocale(Locale.FRANCE);

String horaES = medioDia.format(formateadorES);  // "12:00 p. m." (puede variar según la JVM)
String horaUS = medioDia.format(formateadorUS);  // "12:00 PM"
String horaFR = medioDia.format(formateadorFR);  // "12h00"

System.out.println("Formato español: " + horaES);
System.out.println("Formato estadounidense: " + horaUS);
System.out.println("Formato francés: " + horaFR);

Integración con Duration

La clase Duration representa una cantidad de tiempo en términos de segundos y nanosegundos, y es ideal para trabajar con intervalos de tiempo. Aunque ya vimos algunas operaciones básicas con Duration en la sección anterior, ahora profundizaremos en su integración con LocalTime.

Creación de objetos Duration

Existen varias formas de crear objetos Duration:

// Crear Duration directamente
Duration unaHora = Duration.ofHours(1);
Duration dosMinutos = Duration.ofMinutes(2);
Duration tresSegundos = Duration.ofSeconds(3);
Duration milisegundos = Duration.ofMillis(500);
Duration nanosegundos = Duration.ofNanos(1_000_000);

// Crear Duration combinando unidades
Duration compleja = Duration.ofHours(2)
                           .plusMinutes(30)
                           .plusSeconds(15);

// Crear Duration entre dos instantes temporales
LocalTime inicio = LocalTime.of(9, 0);
LocalTime fin = LocalTime.of(10, 30);
Duration duracionClase = Duration.between(inicio, fin);  // 1 hora y 30 minutos

System.out.println("Duración de clase: " + duracionClase);

Formateo personalizado de Duration

A diferencia de LocalTime, la clase Duration no tiene un método format() directo. Para presentar una duración de manera legible, podemos implementar nuestras propias soluciones:

Duration duracion = Duration.ofHours(2).plusMinutes(45).plusSeconds(10);

// Método 1: Extraer componentes manualmente
long horas = duracion.toHours();
int minutos = duracion.toMinutesPart();
int segundos = duracion.toSecondsPart();
String formatoManual = String.format("%d:%02d:%02d", horas, minutos, segundos);  // "2:45:10"

// Método 2: Usar LocalTime para formatear (si la duración es menor a 24 horas)
LocalTime tiempoDuracion = LocalTime.of(0, 0).plus(duracion);
String formatoConLocalTime = tiempoDuracion.format(DateTimeFormatter.ofPattern("HH:mm:ss"));  // "02:45:10"

System.out.println("Duración formateada manualmente: " + formatoManual);
System.out.println("Duración formateada con LocalTime: " + formatoConLocalTime);

Para duraciones que pueden exceder las 24 horas, necesitamos un enfoque diferente:

public static String formatearDuracion(Duration duracion) {
    long dias = duracion.toDays();
    long horas = duracion.toHoursPart();
    int minutos = duracion.toMinutesPart();
    int segundos = duracion.toSecondsPart();
    
    StringBuilder sb = new StringBuilder();
    if (dias > 0) {
        sb.append(dias).append("d ");
    }
    if (horas > 0 || dias > 0) {
        sb.append(horas).append("h ");
    }
    if (minutos > 0 || horas > 0 || dias > 0) {
        sb.append(minutos).append("m ");
    }
    sb.append(segundos).append("s");
    
    return sb.toString();
}

// Ejemplo de uso
Duration larga = Duration.ofDays(2).plusHours(5).plusMinutes(30).plusSeconds(15);
System.out.println("Duración larga: " + formatearDuracion(larga));  // "2d 5h 30m 15s"

Conversión entre Duration y LocalTime

Podemos utilizar Duration para manipular objetos LocalTime y viceversa:

// Convertir LocalTime a Duration (desde medianoche)
LocalTime horaTrabajo = LocalTime.of(8, 30);
Duration desdeMedianoche = Duration.between(LocalTime.MIDNIGHT, horaTrabajo);  // 8 horas y 30 minutos

// Aplicar una Duration a un LocalTime
LocalTime inicio = LocalTime.of(9, 0);
Duration duracionReunion = Duration.ofMinutes(45);
LocalTime finReunion = inicio.plus(duracionReunion);  // 9:45

System.out.println("Duración desde medianoche: " + desdeMedianoche);
System.out.println("Hora de inicio: " + inicio);
System.out.println("Duración de la reunión: " + duracionReunion);
System.out.println("Hora de finalización: " + finReunion);

Ejemplo práctico: Temporizador de intervalos

Un caso de uso común que combina LocalTime y Duration es un temporizador para entrenamientos por intervalos:

public class TemporizadorIntervalos {
    private Duration duracionActividad;
    private Duration duracionDescanso;
    private int repeticiones;
    
    public TemporizadorIntervalos(Duration actividad, Duration descanso, int repeticiones) {
        this.duracionActividad = actividad;
        this.duracionDescanso = descanso;
        this.repeticiones = repeticiones;
    }
    
    public void mostrarPlanEntrenamiento() {
        LocalTime horaActual = LocalTime.now();
        System.out.println("Plan de entrenamiento a partir de: " + 
                          horaActual.format(DateTimeFormatter.ofPattern("HH:mm:ss")));
        
        Duration duracionTotal = Duration.ZERO;
        
        for (int i = 1; i <= repeticiones; i++) {
            // Calcular hora de inicio y fin de la actividad
            LocalTime inicioActividad = horaActual.plus(duracionTotal);
            duracionTotal = duracionTotal.plus(duracionActividad);
            LocalTime finActividad = horaActual.plus(duracionTotal);
            
            System.out.printf("Intervalo %d - Actividad: %s a %s (%s)%n", 
                i,
                inicioActividad.format(DateTimeFormatter.ofPattern("HH:mm:ss")),
                finActividad.format(DateTimeFormatter.ofPattern("HH:mm:ss")),
                formatearDuracion(duracionActividad));
            
            // Si no es la última repetición, añadir descanso
            if (i < repeticiones) {
                LocalTime inicioDescanso = finActividad;
                duracionTotal = duracionTotal.plus(duracionDescanso);
                LocalTime finDescanso = horaActual.plus(duracionTotal);
                
                System.out.printf("         - Descanso: %s a %s (%s)%n", 
                    inicioDescanso.format(DateTimeFormatter.ofPattern("HH:mm:ss")),
                    finDescanso.format(DateTimeFormatter.ofPattern("HH:mm:ss")),
                    formatearDuracion(duracionDescanso));
            }
        }
        
        // Mostrar duración total del entrenamiento
        System.out.println("\nDuración total del entrenamiento: " + formatearDuracion(duracionTotal));
        System.out.println("Hora estimada de finalización: " + 
                          horaActual.plus(duracionTotal).format(DateTimeFormatter.ofPattern("HH:mm:ss")));
    }
    
    private String formatearDuracion(Duration duracion) {
        long minutos = duracion.toMinutes();
        int segundos = duracion.toSecondsPart();
        return String.format("%02d:%02d", minutos, segundos);
    }
    
    public static void main(String[] args) {
        // Crear un temporizador para 4 intervalos de 5 minutos de actividad y 1 minuto de descanso
        TemporizadorIntervalos temporizador = new TemporizadorIntervalos(
            Duration.ofMinutes(5),
            Duration.ofMinutes(1),
            4
        );
        
        temporizador.mostrarPlanEntrenamiento();
    }
}

Este ejemplo muestra cómo podemos combinar LocalTime y Duration para crear un planificador de entrenamientos por intervalos, calculando y formateando los tiempos de inicio y fin de cada actividad y descanso.

Integración con otras clases temporales

Además de Duration, LocalTime puede integrarse con otras clases del paquete java.time:

Combinación con LocalDate para crear LocalDateTime

LocalDate hoy = LocalDate.now();
LocalTime ahora = LocalTime.now();

// Combinar fecha y hora
LocalDateTime fechaHoraActual = LocalDateTime.of(hoy, ahora);
// Alternativa: LocalDateTime fechaHoraActual = ahora.atDate(hoy);

System.out.println("Fecha y hora actual: " + fechaHoraActual);

Uso con Period para cálculos basados en unidades de calendario

Aunque Period está diseñado principalmente para trabajar con fechas, podemos usarlo en combinación con LocalTime en ciertos escenarios:

LocalTime horaBase = LocalTime.of(10, 0);
Period unMes = Period.ofMonths(1);

// Simulación: ¿Qué hora será en la misma hora del día dentro de un mes?
LocalDateTime fechaHoraBase = horaBase.atDate(LocalDate.now());
LocalDateTime fechaHoraFutura = fechaHoraBase.plus(unMes);
LocalTime horaFutura = fechaHoraFutura.toLocalTime();

System.out.println("Hora base: " + horaBase);
System.out.println("Misma hora dentro de un mes: " + horaFutura);
// Normalmente serán iguales, a menos que haya cambio de horario de verano

Conversión entre formatos de tiempo

En ocasiones necesitamos convertir entre diferentes representaciones de tiempo:

// Convertir segundos desde medianoche a LocalTime
int segundosDesdeMedianoche = 43200;  // 12 horas en segundos
LocalTime medioDia = LocalTime.ofSecondOfDay(segundosDesdeMedianoche);

// Convertir nanosegundos desde medianoche a LocalTime
long nanosDesdeMedianoche = 555_000_000_000L;  // 9:15:00 en nanosegundos
LocalTime mañana = LocalTime.ofNanoOfDay(nanosDesdeMedianoche);

// Convertir LocalTime a segundos o nanosegundos desde medianoche
LocalTime tiempo = LocalTime.of(15, 30);
int segundos = tiempo.toSecondOfDay();       // 55800 segundos
long nanos = tiempo.toNanoOfDay();           // 55800000000000 nanosegundos

System.out.println("Mediodía: " + medioDia);
System.out.println("Mañana: " + mañana);
System.out.println("Segundos desde medianoche para 15:30: " + segundos);

Estas conversiones son útiles cuando necesitamos interoperar con sistemas que utilizan representaciones numéricas del tiempo o para realizar cálculos específicos.

CONSTRUYE TU CARRERA EN IA Y PROGRAMACIÓN SOFTWARE

Accede a +1000 lecciones y cursos con certificado. Mejora tu portfolio con certificados de superación para tu CV.

30 % DE DESCUENTO

Plan mensual

19.00 /mes

13.30 € /mes

Precio normal mensual: 19 €
63 % DE DESCUENTO

Plan anual

10.00 /mes

7.00 € /mes

Ahorras 144 € al año
Precio normal anual: 120 €
Aprende Java online

Ejercicios de esta lección LocalTime

Evalúa tus conocimientos de esta lección LocalTime con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Streams: match

Test

Gestión de errores y excepciones

Código

CRUD en Java de modelo Customer sobre un ArrayList

Proyecto

Clases abstractas

Test

Listas

Código

Métodos de la clase String

Código

Streams: reduce()

Test

API java.nio 2

Puzzle

Polimorfismo

Código

Pattern Matching

Código

Streams: flatMap()

Test

Llamada y sobrecarga de funciones

Puzzle

Métodos referenciados

Test

Métodos de la clase String

Código

Representación de Fecha

Puzzle

Operadores lógicos

Test

Inferencia de tipos con var

Código

Tipos de datos

Código

Estructuras de iteración

Puzzle

Streams: forEach()

Test

Objetos

Puzzle

Funciones lambda

Test

Uso de Scanner

Puzzle

Tipos de variables

Puzzle

Streams: collect()

Puzzle

Operadores aritméticos

Puzzle

Arrays y matrices

Código

Clases y objetos

Código

Interfaz funcional Consumer

Test

CRUD en Java de modelo Customer sobre un HashMap

Proyecto

Interfaces

Código

Enumeraciones Enums

Código

API Optional

Test

Interfaz funcional Function

Test

Encapsulación

Test

Interfaces

Código

Uso de API Optional

Puzzle

Representación de Hora

Test

Herencia básica

Test

Clases y objetos

Código

Interfaz funcional Supplier

Puzzle

HashMap

Puzzle

Sobrecarga de métodos

Test

Polimorfismo de tiempo de ejecución

Puzzle

OOP en Java

Proyecto

Sobrecarga de métodos

Código

CRUD de productos en Java

Proyecto

Clases sealed

Código

Creación de Streams

Test

Records

Código

Encapsulación

Código

Streams: min max

Puzzle

Herencia

Código

Métodos avanzados de la clase String

Puzzle

Funciones

Código

Polimorfismo de tiempo de compilación

Test

Reto sintaxis Java

Proyecto

Conjuntos

Código

Estructuras de control

Código

Recursión

Código

Excepciones

Puzzle

Herencia avanzada

Puzzle

Estructuras de selección

Test

Uso de interfaces

Test

Operadores

Código

Variables

Código

HashSet

Test

Objeto Scanner

Test

Streams: filter()

Puzzle

Operaciones de Streams

Puzzle

Interfaz funcional Predicate

Puzzle

Streams: sorted()

Test

Configuración de entorno

Test

Uso de variables

Test

Clases

Test

Streams: distinct()

Puzzle

Streams: count()

Test

ArrayList

Test

Mapas

Código

Datos de referencia

Test

Interfaces funcionales

Puzzle

Métodos básicos de la clase String

Test

Tipos de datos

Código

Clases abstractas

Código

Instalación

Test

Funciones

Código

Excepciones

Código

Estructuras de control

Código

Herencia de clases

Código

La clase Scanner

Código

Generics

Código

Streams: map()

Puzzle

Funciones y encapsulamiento

Test

Todas las lecciones de Java

Accede a todas las lecciones de Java y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Instalación De Java

Introducción Y Entorno

Configuración De Entorno Java

Introducción Y Entorno

Tipos De Datos

Sintaxis

Variables

Sintaxis

Operadores

Sintaxis

Estructuras De Control

Sintaxis

Funciones

Sintaxis

Recursión

Sintaxis

Arrays Y Matrices

Sintaxis

Excepciones

Programación Orientada A Objetos

Clases Y Objetos

Programación Orientada A Objetos

Encapsulación

Programación Orientada A Objetos

Herencia

Programación Orientada A Objetos

Clases Abstractas

Programación Orientada A Objetos

Interfaces

Programación Orientada A Objetos

Sobrecarga De Métodos

Programación Orientada A Objetos

Polimorfismo

Programación Orientada A Objetos

La Clase Scanner

Programación Orientada A Objetos

Métodos De La Clase String

Programación Orientada A Objetos

Excepciones

Programación Orientada A Objetos

Records

Programación Orientada A Objetos

Pattern Matching

Programación Orientada A Objetos

Inferencia De Tipos Con Var

Programación Orientada A Objetos

Enumeraciones Enums

Programación Orientada A Objetos

Generics

Programación Orientada A Objetos

Clases Sealed

Programación Orientada A Objetos

Listas

Framework Collections

Conjuntos

Framework Collections

Mapas

Framework Collections

Funciones Lambda

Programación Funcional

Interfaz Funcional Consumer

Programación Funcional

Interfaz Funcional Predicate

Programación Funcional

Interfaz Funcional Supplier

Programación Funcional

Interfaz Funcional Function

Programación Funcional

Métodos Referenciados

Programación Funcional

Creación De Streams

Programación Funcional

Operaciones Intermedias Con Streams: Map()

Programación Funcional

Operaciones Intermedias Con Streams: Filter()

Programación Funcional

Operaciones Intermedias Con Streams: Distinct()

Programación Funcional

Operaciones Finales Con Streams: Collect()

Programación Funcional

Operaciones Finales Con Streams: Min Max

Programación Funcional

Operaciones Intermedias Con Streams: Flatmap()

Programación Funcional

Operaciones Intermedias Con Streams: Sorted()

Programación Funcional

Operaciones Finales Con Streams: Reduce()

Programación Funcional

Operaciones Finales Con Streams: Foreach()

Programación Funcional

Operaciones Finales Con Streams: Count()

Programación Funcional

Operaciones Finales Con Streams: Match

Programación Funcional

Api Optional

Programación Funcional

Transformación

Programación Funcional

Reducción Y Acumulación

Programación Funcional

Mapeo

Programación Funcional

Streams Paralelos

Programación Funcional

Agrupación Y Partición

Programación Funcional

Filtrado Y Búsqueda

Programación Funcional

Api Java.nio 2

Entrada Y Salida Io

Fundamentos De Io

Entrada Y Salida Io

Leer Y Escribir Archivos

Entrada Y Salida Io

Httpclient Moderno

Entrada Y Salida Io

Clases De Nio2

Entrada Y Salida Io

Api Java.time

Api Java.time

Localtime

Api Java.time

Localdatetime

Api Java.time

Localdate

Api Java.time

Executorservice

Concurrencia

Virtual Threads (Project Loom)

Concurrencia

Future Y Completablefuture

Concurrencia

Spring Framework

Frameworks Para Java

Micronaut

Frameworks Para Java

Maven

Frameworks Para Java

Gradle

Frameworks Para Java

Lombok Para Java

Frameworks Para Java

Quarkus

Frameworks Para Java

Ecosistema Jakarta Ee De Java

Frameworks Para Java

Introducción A Junit 5

Testing

Accede GRATIS a Java y certifícate

Certificados de superación de Java

Supera todos los ejercicios de programación del curso de Java y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender la creación y manipulación básica de objetos LocalTime.
  • Realizar operaciones aritméticas y comparaciones entre instantes de tiempo.
  • Formatear LocalTime y combinarlo con otras clases temporales como Duration.
  • Implementar ejemplos prácticos de control de horarios y planificación de citas.
  • Gestionar conversiones y ajustes temporales con LocalTime y Duration.