CodeGym /Corsi /JAVA 25 SELF /Calcoli e confronto di date, Duration, Period

Calcoli e confronto di date, Duration, Period

JAVA 25 SELF
Livello 13 , Lezione 5
Disponibile

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
Period
Differenza tra date Quanti anni/mesi/giorni tra due date
Duration
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).

1
Compito
JAVA 25 SELF, livello 13, lezione 5
Bloccato
Conto alla rovescia per la festa 🎉
Conto alla rovescia per la festa 🎉
1
Compito
JAVA 25 SELF, livello 13, lezione 5
Bloccato
Macchina del tempo: verifica del raggiungimento della data 🕰️
Macchina del tempo: verifica del raggiungimento della data 🕰️
1
Compito
JAVA 25 SELF, livello 13, lezione 5
Bloccato
Gestione del progetto: quanti giorni mancano alla scadenza? 🗓️
Gestione del progetto: quanti giorni mancano alla scadenza? 🗓️
1
Compito
JAVA 25 SELF, livello 13, lezione 5
Bloccato
Agenzia immobiliare: calcolo dell'età dell'edificio 🏡
Agenzia immobiliare: calcolo dell'età dell'edificio 🏡
1
Sondaggio/quiz
Date e orari, livello 13, lezione 5
Non disponibile
Date e orari
Date, orari e fusi orari
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION