Java LocalTime
Rappresenta orari senza data né fuso orario in Java con LocalTime. Scopri creazione, aritmetica e confronto.
LocalTime è il corrispettivo di LocalDate: un'ora del giorno — ora, minuto, secondo, nanosecondo — senza data e senza fuso orario. Rappresenta la stessa lettura dell'orologio da parete in qualsiasi giorno del calendario, ovunque: LocalTime.of(9, 30) è le nove e mezza in qualsiasi giorno, in qualsiasi città.
È il tipo giusto per un orario ricorrente — un negozio che apre alle 09:30, un job giornaliero alle 03:15, una riunione che inizia alle 14:00 indipendentemente dalla data. Non è il tipo giusto per "il momento in cui l'utente ha cliccato su Invia alle 14:30 di oggi" — quello richiede una data, e probabilmente un fuso orario. I due combinati danno LocalDateTime, l'argomento del prossimo capitolo.
Creazione
LocalTime now = LocalTime.now(); // current time in the JVM default zone
LocalTime nine = LocalTime.of(9, 0); // hour, minute
LocalTime nineThirty = LocalTime.of(9, 30, 15); // hour, minute, second
LocalTime nineThirtyNanos = LocalTime.of(9, 30, 15, 500_000_000); // + nanosecond (0 ..999_999_999)
LocalTime parsed = LocalTime.parse("09:30:15"); // ISO-8601 HH:mm[:ss[.nnnnnnnnn]]Le costanti predefinite sono utili per i casi limite:
LocalTime.MIDNIGHT // 00:00
LocalTime.NOON // 12:00
LocalTime.MIN // 00:00:00.000000000
LocalTime.MAX // 23:59:59.999999999MIN e MAX sono particolarmente utili quando vengono combinati con un LocalDate per coprire un intero giorno: LocalDateTime.of(date, LocalTime.MIN) è "la mezzanotte all'inizio della data"; LocalTime.MAX è l'ultimo nanosecondo rappresentabile del giorno.
Risoluzione: nanosecondi
LocalTime è preciso al nanosecondo — una risoluzione a nove cifre (1 secondo = 1.000.000.000 ns). Sulla maggior parte dei sistemi operativi la risoluzione effettiva dell'orologio è il millisecondo (1.000.000 ns) o il microsecondo (1.000 ns); la precisione aggiuntiva è presente affinché il tipo non perda informazioni quando interagisce con sistemi che dispongono di orologi ad alta risoluzione.
Accessori diretti:
time.getHour(); // 0-23
time.getMinute(); // 0-59
time.getSecond(); // 0-59
time.getNano(); // 0-999_999_999Non esiste getMilli(); se si vogliono i millisecondi, si divide il nano: time.getNano() / 1_000_000.
24 ore, senza AM/PM
LocalTime è internamente a 24 ore. LocalTime.of(13, 0) è "1 PM" e nel tipo non esiste AM/PM. Il parsing di stringhe con "AM"/"PM" richiede un DateTimeFormatter personalizzato (il capitolo Parsing delle date lo tratta) — il parse predefinito accetta solo il formato ISO-8601 a 24 ore.
Aritmetica e modifiche
Stessa struttura fluente di LocalDate:
time.plusHours(2);
time.plusMinutes(30);
time.plusSeconds(45);
time.plusNanos(500_000);
time.withHour(14); // replace one field
time.withMinute(0);Il comportamento di scorrimento: ogni metodo plus/minus su LocalTime scorre silenziosamente oltre la mezzanotte. LocalTime.of(23, 0).plusHours(2) restituisce 01:00, non "domani all'01:00" — in LocalTime non esiste il "domani". Se hai bisogno di sapere se è avvenuto uno scorrimento, usa LocalDateTime oppure esegui il calcolo manualmente:
LocalTime late = LocalTime.of(23, 0);
LocalTime later = late.plusHours(2); // 01:00 — silently wrapped
// To detect wrap: compare the new value's getHour with what you expected, or use LocalDateTime.Questo scorrimento è documentato e intenzionale, ma è un trabocchetto se lo si dimentica. Per calcoli come "quando finisce questo turno?" che possono attraversare la mezzanotte, il tipo corretto è LocalDateTime, non LocalTime.
Confronto
time.isBefore(other);
time.isAfter(other);
time.compareTo(other);
time.equals(other);Ordinamento lessicografico per ora:minuto:secondo:nano. LocalTime implementa Comparable<LocalTime>, quindi è possibile ordinare una lista di orari o usarlo direttamente come chiave di una TreeMap.
Distanza
Sia Duration.between che ChronoUnit.X.between funzionano:
Duration d = Duration.between(start, end);
long minutes = ChronoUnit.MINUTES.between(start, end);
long seconds = ChronoUnit.SECONDS.between(start, end);Il segno: positivo quando end è dopo start, negativo altrimenti. Si applica la stessa avvertenza sullo scorrimento — Duration.between(LocalTime.of(23, 0), LocalTime.of(1, 0)) restituisce −22 ore, non +2 ore; l'API tratta 01:00 come precedente a 23:00 dello stesso giorno convenzionale. Per "il turno è andato oltre la mezzanotte", l'aritmetica basata su LocalDateTime è lo strumento giusto.
Combinazione con LocalDate
Spesso si converte in una data con orario:
LocalDate date = LocalDate.of(2025, 11, 4);
LocalTime time = LocalTime.of(9, 30);
LocalDateTime dt = date.atTime(time); // 2025-11-04T09:30
LocalDateTime dt2 = time.atDate(date); // same thingatTime / atDate sono i metodi ponte. Il risultato è un LocalDateTime — ancora senza fuso orario, ma ora ancorato a un giorno del calendario. Il prossimo capitolo approfondisce ulteriormente.
Un esempio pratico: un piccolo assistente per la pianificazione
Il programma seguente usa LocalTime per un'attività di tipo agenda giornaliera: definisce una finestra di "orario di ufficio", verifica se un determinato momento rientra in essa, calcola quanto manca alla prossima apertura e dimostra il trabocchetto dello scorrimento della mezzanotte.
Cosa ricavare dall'esecuzione:
LocalTimeè stampato come09:00,17:30,12:30— il formato canonico ISO-8601 a 24 ore. Nessun AM/PM nel tipo. Se è necessario mostrare "5:30 PM" all'utente, il capitolo sulla Formattazione delle date contiene il formatter appropriato; il tipo in sé non ne sa nulla.- Il controllo "l'orario è dentro la finestra" ha usato
!isBefore(open) && !isAfter(close). È l'idioma dell'intervallo semi-aperto rispetto a quello chiuso — entrambi gli estremi sono inclusi. Per "strettamente interno", si usano le forme non negate. Duration.between(LocalTime.of(22, 0), LocalTime.of(2, 0))ha restituitoPT-20H, nonPT4H.LocalTimenon ha nozione di "giorno successivo" — quandoendè precedente astartin termini di orologio, la durata diventa negativa. Per un turno che attraversa la mezzanotte, si passano gli input aLocalDateTimee si lascia che le date risolvano l'ambiguità. Questo è il principale trabocchetto diLocalTime.LocalTime.of(23, 30).plusHours(2)ha restituito01:30. Lo scorrimento è silenzioso — nessuna eccezione, nessun flag, nessun riporto nella data. Se è necessario sapere "c'è stato uno scorrimento?", si usaLocalDateTime. Se si vuole davvero un'aritmetica mod-24 dell'orologio (ad esempio per un piano ricorrente), lo scorrimento è il comportamento corretto.date.atTime(time)è stato il ponte canonico versoLocalDateTime. Il suo specularetime.atDate(date)produce lo stesso risultato. Li userai continuamente quando leggi un orario da una fonte e una data da un'altra, per combinarli nell'oggetto singolo richiesto dall'API a valle.
Prossimo argomento
Il prossimo capitolo, Java LocalDateTime, combina LocalDate e LocalTime nel terzo tipo "locale": una data e un orario, ancora senza fuso orario. È l'unità naturale per "questo è accaduto alle 14:30 del 4 novembre" quando il fuso orario è irrilevante o registrato separatamente.