W3docs

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.999999999

MIN 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_999

Non 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 thing

atTime / 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.

java— editable, runs on the server

Cosa ricavare dall'esecuzione:

  • LocalTime è stampato come 09: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 restituito PT-20H, non PT4H. LocalTime non ha nozione di "giorno successivo" — quando end è precedente a start in termini di orologio, la durata diventa negativa. Per un turno che attraversa la mezzanotte, si passano gli input a LocalDateTime e si lascia che le date risolvano l'ambiguità. Questo è il principale trabocchetto di LocalTime.
  • LocalTime.of(23, 30).plusHours(2) ha restituito 01:30. Lo scorrimento è silenzioso — nessuna eccezione, nessun flag, nessun riporto nella data. Se è necessario sapere "c'è stato uno scorrimento?", si usa LocalDateTime. 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 verso LocalDateTime. Il suo speculare time.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.

Esercizi

Pratica
Cosa restituisce `LocalTime.of(23, 0).plusHours(3)` e perché?
Cosa restituisce `LocalTime.of(23, 0).plusHours(3)` e perché?
Was this page helpful?