1. Aggiunta e sottrazione di date e orari
Nella programmazione lavorare con date e orari non significa solo “stampare una data in modo carino sullo schermo”. Molto spesso serve:
- sapere quanti giorni mancano a un evento importante;
- calcolare l’età dell’utente;
- determinare quanto tempo è trascorso tra due eventi;
- verificare se la scadenza è già arrivata;
- aggiungere a una data un certo numero di giorni, settimane, mesi o ore.
Ad esempio, nella nostra applicazione vogliamo ricordare all’utente che alla scadenza dell’attività mancano 3 giorni. Oppure congratularci per il compleanno già passato (se la data è già nel passato).
Per questo in java.time ci sono classi e metodi speciali che rendono tali calcoli semplici e sicuri.
Metodi principali per sommare e sottrarre
Tutte le classi di data e ora (LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant) hanno i metodi:
- plusXxx() — aggiungere (giorni, mesi, anni, ore, minuti, ecc.)
- minusXxx() — sottrarre (idem)
import java.time.LocalDate;
LocalDate today = LocalDate.now(); // Data odierna
LocalDate tomorrow = today.plusDays(1); // Domani
LocalDate nextMonth = today.plusMonths(1); // Tra un mese
LocalDate lastWeek = today.minusWeeks(1); // Una settimana fa
System.out.println("Oggi: " + today);
System.out.println("Domani: " + tomorrow);
System.out.println("Tra un mese: " + nextMonth);
System.out.println("Una settimana fa: " + lastWeek);
Tutti questi metodi restituiscono un nuovo oggetto e non modificano quello originale. L’immutabilità è tutto!
import java.time.LocalTime;
LocalTime now = LocalTime.now();
LocalTime inTwoHours = now.plusHours(2);
LocalTime tenMinutesAgo = now.minusMinutes(10);
System.out.println("Adesso: " + now);
System.out.println("Tra 2 ore: " + inTwoHours);
System.out.println("10 minuti fa: " + tenMinutesAgo);
Metodi combinati
LocalDate vacation = today.plusMonths(2).plusDays(10);
System.out.println("Ferie: " + vacation);
2. Ottenere la differenza tra date: Period e Duration
Quando bisogna sapere quanto tempo è passato tra due date o istanti, entrano in scena due protagonisti — Period e Duration. Conosciamoli più da vicino.
Qual è la differenza tra Period e Duration?
- Period — per lavorare con le date (anno, mese, giorno). Ad esempio, “3 anni, 2 mesi e 5 giorni”.
- Duration — per lavorare con il tempo (ore, minuti, secondi, nanosecondi). Ad esempio, “5 ore e 30 minuti”.
| Classe | A cosa serve | Esempio d’uso |
|---|---|---|
|
Differenza tra date | Quanti anni/mesi/giorni tra due date |
|
Differenza tra istanti | Quante ore/minuti/secondi tra eventi |
Esempio: calcolare l’età dell’utente
import java.time.LocalDate;
import java.time.Period;
LocalDate birthday = LocalDate.of(2000, 1, 15); // Compleanno
LocalDate today = LocalDate.now();
Period age = Period.between(birthday, today);
System.out.println("Età: " + age.getYears() + " anni, " +
age.getMonths() + " mesi, " +
age.getDays() + " giorni");
Analogia: Period è come la differenza “umana” tra date (“ho 24 anni, 5 mesi e 12 giorni”).
Esempio: quanto tempo manca alla scadenza
import java.time.LocalDate;
LocalDate deadline = LocalDate.of(2025, 7, 1);
LocalDate today = LocalDate.now();
if (today.isBefore(deadline)) {
Period left = Period.between(today, deadline);
System.out.println("Alla scadenza mancano: " +
left.getMonths() + " mesi e " +
left.getDays() + " giorni");
} else {
System.out.println("La scadenza è già passata!");
}
Duration: differenza nel tempo
import java.time.LocalDateTime;
import java.time.Duration;
LocalDateTime start = LocalDateTime.of(2025, 6, 1, 10, 0, 0);
LocalDateTime end = LocalDateTime.of(2025, 6, 1, 15, 30, 0);
Duration duration = Duration.between(start, end);
System.out.println("Durata: " + duration.toHours() + " ore " +
(duration.toMinutes() % 60) + " minuti");
Duration misura la differenza in secondi, minuti, ore, giorni (ma i giorni sono sempre di 24 ore, senza considerare le peculiarità del calendario).
Confronto: quando usare Period e quando Duration?
- Se avete solo date (senza orario) — usate Period.
- Se avete anche il tempo (per esempio, LocalDateTime, Instant) — usate Duration.
3. Confronto di date e orari: isBefore, isAfter, equals
A volte bisogna solo capire: la data è già arrivata oppure no? L’evento è nel passato o nel futuro? Per questo tutte le classi di data e ora hanno i metodi:
- isBefore(altraData)
- isAfter(altraData)
- isEqual(altraData) (o semplicemente equals)
import java.time.LocalDate;
LocalDate today = LocalDate.now();
LocalDate deadline = LocalDate.of(2025, 7, 1);
if (today.isBefore(deadline)) {
System.out.println("C’è ancora tempo!");
} else if (today.isEqual(deadline)) {
System.out.println("Oggi è la scadenza!");
} else {
System.out.println("La scadenza è già passata :(");
}
import java.time.LocalTime;
LocalTime now = LocalTime.now();
LocalTime lunch = LocalTime.of(13, 0);
if (now.isAfter(lunch)) {
System.out.println("Il pranzo c’è già stato!");
} else {
System.out.println("C’è ancora tempo prima di pranzo.");
}
Importante: si possono confrontare solo oggetti dello stesso tipo (LocalDate con LocalDate, LocalDateTime con LocalDateTime, ecc.).
4. Pratica: esercizi sul calcolo delle differenze e il controllo delle scadenze
Esempio: quanti giorni mancano alla scadenza di un’attività
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
LocalDate today = LocalDate.now();
LocalDate deadline = LocalDate.of(2025, 7, 1);
long daysLeft = ChronoUnit.DAYS.between(today, deadline);
if (daysLeft > 0) {
System.out.println("Alla scadenza mancano " + daysLeft + " giorni");
} else if (daysLeft == 0) {
System.out.println("Oggi è la scadenza!");
} else {
System.out.println("La scadenza è passata " + Math.abs(daysLeft) + " giorni fa");
}
ChronoUnit.DAYS.between() — un modo comodo per conoscere il numero esatto di giorni tra due date (senza tener conto di mesi e anni).
Esempio: quanti secondi tra due eventi
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
LocalDateTime start = LocalDateTime.of(2025, 6, 1, 10, 0, 0);
LocalDateTime end = LocalDateTime.of(2025, 6, 1, 15, 30, 0);
long seconds = ChronoUnit.SECONDS.between(start, end);
System.out.println("Tra gli eventi sono passati " + seconds + " secondi");
Esempio: calcolo dell’età di un’attività
import java.time.LocalDate;
import java.time.Period;
LocalDate created = LocalDate.of(2025, 5, 20);
LocalDate today = LocalDate.now();
Period period = Period.between(created, today);
System.out.println("L’attività è stata creata " +
period.getDays() + " giorni, " +
period.getMonths() + " mesi e " +
period.getYears() + " anni fa.");
Esempio: durata tra due Instant
import java.time.Instant;
import java.time.Duration;
Instant start = Instant.now();
// ... facciamo qualcosa ...
Instant end = Instant.now();
Duration duration = Duration.between(start, end);
System.out.println("L’esecuzione ha impiegato " + duration.toMillis() + " millisecondi");
5. Particolarità d’uso di Period e Duration
Particolarità di Period
- Period calcola la differenza secondo il calendario: tra il 28 febbraio e il 1 marzo c’è 1 giorno, anche se sono mesi diversi.
- Si può ottenere il numero di anni, mesi, giorni separatamente: getYears(), getMonths(), getDays().
- Se serve conoscere il numero totale di giorni tra due date — usate ChronoUnit.DAYS.between().
Particolarità di Duration
- Duration lavora con il tempo esatto (ore, minuti, secondi).
- Può funzionare con LocalTime, LocalDateTime, Instant.
- Non si può usare per date senza orario (LocalDate) — si otterrà un’eccezione.
Esempio: differenza tra Period e Duration
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Duration;
import java.time.Period;
LocalDate date1 = LocalDate.of(2025, 2, 28);
LocalDate date2 = LocalDate.of(2025, 3, 1);
Period period = Period.between(date1, date2); // 2 giorni (anno bisestile)
long days = java.time.temporal.ChronoUnit.DAYS.between(date1, date2); // 2 giorni
System.out.println("Period: " + period.getDays() + " giorni");
System.out.println("ChronoUnit: " + days + " giorni");
LocalDateTime dt1 = LocalDateTime.of(2025, 6, 1, 23, 0);
LocalDateTime dt2 = LocalDateTime.of(2025, 6, 2, 1, 0);
Duration duration = Duration.between(dt1, dt2); // 2 ore
System.out.println("Duration: " + duration.toHours() + " ore");
6. Uso di Duration e Period per mostrare la differenza in modo comodo
Quando calcolate la differenza tra date o orari per l’utente, non è sempre comodo mostrare “123456 secondi”. Di solito si preferisce qualcosa come “2 giorni 3 ore 15 minuti”.
Esempio: stampa della differenza tra date e orari
import java.time.LocalDateTime;
import java.time.Duration;
LocalDateTime start = LocalDateTime.of(2025, 6, 1, 14, 0);
LocalDateTime end = LocalDateTime.of(2025, 6, 3, 16, 30);
Duration duration = Duration.between(start, end);
long days = duration.toDays();
long hours = duration.minusDays(days).toHours();
long minutes = duration.minusDays(days).minusHours(hours).toMinutes();
System.out.println("Differenza: " + days + " giorni " +
hours + " ore " + minutes + " minuti");
7. Particolarità nel lavoro con ZonedDateTime e Instant
- La differenza tra due ZonedDateTime in fusi diversi è calcolata sul tempo assoluto e non sul tempo “umano” di ciascun fuso.
- Il passaggio all’ora legale/solare può influire sulla differenza in ore tra le date.
Esempio: differenza tra ZonedDateTime
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.Duration;
ZonedDateTime MinskTime = ZonedDateTime.of(2025, 6, 1, 12, 0, 0, 0, ZoneId.of("Europe/Minsk"));
ZonedDateTime nyTime = ZonedDateTime.of(2025, 6, 1, 5, 0, 0, 0, ZoneId.of("America/New_York"));
Duration diff = Duration.between(nyTime, MinskTime);
System.out.println("Differenza: " + diff.toHours() + " ore");
8. Errori tipici nei calcoli con date e orari
Errore n. 1: confondere Period e Duration.
Se si prova a usare Duration con LocalDate, si otterrà un’eccezione. Per le date usare Period, per il tempo — Duration.
Errore n. 2: non si tengono in considerazione i fusi orari.
Se si confrontano date e orari in fusi diversi si possono ottenere risultati inattesi. Meglio uniformare tutto a un unico fuso o usare Instant.
Errore n. 3: si pensa che i metodi plus/minus modifichino l’oggetto.
Tutti gli oggetti java.time sono immutabili! Non dimenticate di assegnare il risultato a una nuova variabile (per esempio, today = today.plusDays(1)).
Errore n. 4: si usa getDays() di Period pensando che sia il numero totale di giorni.
In realtà sono solo i giorni residui dopo aver sottratto anni e mesi. Per il numero totale di giorni usate ChronoUnit.DAYS.between().
Errore n. 5: si confrontano oggetti di tipi diversi.
I metodi isBefore, isAfter, isEqual funzionano solo per oggetti dello stesso tipo (ad esempio, LocalDate con LocalDate).
GO TO FULL VERSION