Nella parte finale dell'articolo Java: gestione delle date, sono state introdotte le classi java.time.LocalDate
e java.time.LocaleDateTime
al fine di evidenziare la nuova modalità di manipolazione delle date introdotta
a partire da Java 8.
In questo articolo andiamo più in profondità, nuove classi vengono introdotte per illustrare aspetti avanzati come la comparazione di date ed orari e la gestione degli intervalli di tempo.
La classe LocalDate
rappresenta una data in formato ISO (yyyy-MM-dd) priva di ore, minuti e secondi. Il suo utilizzo è indicato in tutti quei casi in cui l'orario non è rilevante nella rappresentazione di una data, si pensi ad esempio ad un giorno di compleanno o ad un giorno di paga. LocalDate
offre tre metodi statici che consentono facilmente di ottenere la data corrente, un specifica data attraverso valori numerici, oppure una data in formato stringa conforme alla specifica ISO:
/*Data corrente (al presente articolo 26/01/2019)*/
LocalDate today = LocalDate.now();
/*Data specficiando anno, mese, giorno*/
LocalDate yesterday = LocalDate.of(2019, 01, 25);
/*Una data specificando una stringa in formato ISO*/
LocalDate tomorrow = LocalDate.parse("2019-01-27");
Per confrontare le date definite nel precedente frammento di codice, utilizziamo i metodi isBefore()
ed isAfter()
della classe LocalDate
:
System.out.println(yesterday.isBefore(today));
System.out.println(tomorrow.isAfter(today));
Grazie a questi metodi siamo in grado di capire facilmente quale data viene prima o dopo di un'altra.
La classe LocalDate
è ricca di metodi che consentono di eseguire operazioni di manipolazione sulle date. Possiamo aggiungere quantità come giorni, settimane, mesi ed anni:
LocalDate plusOneDay = today.plusDays(1);
LocalDate plusOneMonth = today.plusMonths(1);
LocalDate plusOneYear = today.plusYears(1);
LocalDate plusOneWeek = today.plusWeeks(1);
System.out.println(plusOneDay);
System.out.println(plusOneMonth);
System.out.println(plusOneYear);
System.out.println(plusOneWeek);
Oppure sottrarre le stesse quantità:
LocalDate minusOneDay = today.minusDays(1);
LocalDate minusOneMonth = today.minusMonths(1);
LocalDate minusOneYear = today.minusYears(1);
LocalDate minusOneWeek = today.minusWeeks(1);
System.out.println(minusOneDay);
System.out.println(minusOneMonth);
System.out.println(minusOneYear);
System.out.println(minusOneWeek);
Un'alternativa ai metodi precedenti, è l'utilizzo diretto dei metodi plus()
e minus()
attraverso la classe java.time.temporal.ChronoUnit
:
LocalDate plusOneMonth = today.plus(1, ChronoUnit.MONTHS);
LocalDate minusOneMonth = today.minus(1, ChronoUnit.MONTHS);
Molto interessanti sono anche i metodi che offrono la possibilità di conoscere il giorno del mese, della settimana, o dell'anno, contenuti in una data:
LocalDate day = LocalDate.parse("2019-03-27");
System.out.println(day.getDayOfMonth());
System.out.println(day.getDayOfWeek());
System.out.println(day.getDayOfYear());
Ottenendo in stampa:
27
WEDNESDAY
86
Di una data possiamo anche estrarre quelle che vengono definite le informazioni al contorno. Esempi di queste informazioni sono l'inizio del giorno o del mese:
LocalDate day = LocalDate.parse("2019-03-27");
LocalDateTime beginningOfDay = day.atStartOfDay();
LocalDate firstDayOfMonth = day.with(TemporalAdjusters.firstDayOfMonth());
System.out.println(beginningOfDay);
System.out.println(firstDayOfMonth);
Nell'esempio precedente si è fatto uso della classe java.time.temporal.TemporalAdjusters
. Dal codice precedente otteniamo in stampa:
2019-03-27T00:00
2019-03-01
Che rappresentano, rispettivamente, la data di inizio del giorno e la data di inizio mese. Quando l'informazione dell'orario per una data è rilevante, è necessario utilizzare la classe LocalDateTime
. Questa classe offre gli stessi metodi per la manipolazione delle date visti in precedenza, con l'eccezione del formato stringa della data da parsare che cambia attraverso l'introduzione dell'orario nel formato della data stessa, ed il metodo of()
che presenta ulteriori parametri per la definizione di ore, minuti e secondi:
LocalDateTime day = LocalDateTime.of(2019, Month.FEBRUARY, 12, 00, 00);
L'esigenza di gestire orari senza doversi preoccupare di definire necessariamente anche informazioni di anno, mese e giorno, è gestita attraverso la classe java.time.LocalTime
. Vediamo alcuni esempi. Recuperiamo l'orario corrente e definiamo l'orario 5:30 in diverse modalità:
LocalTime time = LocalTime.now();
LocalTime fiveThirty1 = LocalTime.parse("05:30");
LocalTime fiveThirty2 = LocalTime.of(5, 30);
Aggiungiamo un'ora all'orario 5.30:
LocalTime fiveThirty3 = LocalTime.parse("05:30").plus(1, ChronoUnit.HOURS);
Ricaviamo l'informazione specifica dell'ora ed effettuiamo un confronto tra orari:
int five = LocalTime.parse("05:30").getHour();
boolean isbefore = LocalTime.parse("05:30").isBefore(LocalTime.parse("08:30"));
System.out.println(isBefore);
Concludiamo l'articolo con le classi java.time.Period
e java.time.Duaration
completando cosi la visione d'insieme sulla gestione delle date. La classe Period
rappresenta una quantità di tempo espressa in termini di anni, mesi o giorni, mentre Duration
quantità di tempo espresse in secondi o nano secondi.
Possiamo manipolare una data utilizzando un periodo di tempo aggiungendo, ad esempio, 5 giorni alla data corrente:
LocalDate now = LocalDate.now();
LocalDate finalDate = now.plus(Period.ofDays(5));
La classe Period
ha diversi metodi, come ad esempio getYears()
, getMonths()
o getDays()
, che possono essere utilizzati nella gestione delle date per ottenere differenze in termini quantità temporali:
LocalDate day1 = LocalDate.of(2019, 01, 25);
LocalDate day2 = LocalDate.parse("2019-01-27");
int days = Period.between(day1, day2).getDays();
Una variante interessante all'uso di Period
è la classe java.time.temporal.ChronoUnit
:
long days = ChronoUnit.DAYS.between(day1 , day2);
La classe Duration
è particolarmente utile nell'utilizzo congiunto con LocalTime
. Possiamo, ad esempio, definire un orario ed aggiungere successivamente ad esso una quantità di tempo in secondi:
LocalTime initialTime = LocalTime.of(4, 30, 0);
LocalTime finalTime = initialTime.plus(Duration.ofSeconds(13));