In Java per memorizzare una data è possibile utilizzare un oggetto di classe Date. Un oggetto di questa classe tratta una data come un istante di tempo con una precisione del millisecondo e la rappresenta con il numero di millisecondi che la separano dalla data del 1 gennaio 1970, assunta come riferimento. Questo numero intero (di tipo long) è positivo per le date successive a quella di riferimento e negativo per le date anteriori.
Il modo più semplice per creare un oggetto di classe Date che contiene la data corrente è il seguente:
1 |
Date d = new Date(); |
ossia richiamando il costruttore della classe Date senza alcun parametro. Si faccia attenzione perché altri suoi costruttori, così come molti suoi metodi, sono deprecati e nei nuovi progetti non devono essere utilizzati. Per questo motivo per operare correttamente con un oggetto di classe Date, bisogna farlo utilizzando altre classi, quali: DateFormat, Calendar e SimpleDateFormat. In questo articolo illustrerò solo alcune semplici soluzioni che utilizzano queste classi per realizzare le operazioni più comuni sulle date. Per approfondimenti si rimanda alla documentazione del linguaggio Java presente on line (link) e che viene da me utilizzata come fonte di questo articolo.
La classe DateFormat
Questa classe può essere utile per ottenere la conversione di una data di classe Date in una stringa di testo adatta per la visualizzazione e viceversa, consentendo allo stesso tempo di utilizzare diversi stili di visualizzazione, attraverso l’uso di quattro constanti definite nella stessa classe. Le costanti degli stili di visualizzazione di una data sono quelle riportate nella prima colonna della tabella seguente, che riporta anche gli esempi dei diversi formati di data corrispondenti:
Stile | Esempio |
---|---|
SHORT | 05/03/17 |
MEDIUM | 5-mar-2017 |
LONG | 5 marzo 2017 |
FULL | domenica 5 marzo 2017 |
Della classe DateFormat sono molto utili i seguenti metodi:
- DateFormat getDateInstance(int stile, Locale unLocale) – metodo statico che istanzia un oggetto di classe DateFormat secondo un fissato stile di visualizzazione della data; richiede due parametri: il primo imposta lo stile (vedi tabella precedente), il secondo imposta la localizzazione (vedi esempi seguenti).
- String format(Date data) – converte un oggetto di classe Date, che richiede come parametro, in una data sotto forma di una stringa (String), che restituisce al chiamante.
- Date parse(String data) – converte una data fornita come String, che richiede come parametro, in un oggetto di classe Date, che restituisce al chiamante. Se la stringa non può essere convertita lancia un’eccezione di classe ParseException. Affinché però nella conversione questo metodo possa segnalare in maniera rigorosa tutti gli errori, è necessario impostare opportunamente il metodo setLenient().
- void setLenient(boolean clemente) – imposta il tipo di controlli da effettuare durante la conversione di una stringa in un oggetto di classe Date e quindi se segnalare o meno alcuni errori di conversione. Richiede un parametro booleano da impostare su false se si vuole che il metodo parse() non sia clemente, ma al contrario rigoroso, nel calcolo e quindi conversione della data (es. non accetterà una data del tipo 31/02/2017, che per default invece viene accettata e interpretata come 03/04/2017, o un orario del tipo 25:30, che per default viene accettato e interpretato come 01:30 del giorno successivo).
(Visualizzare un data in output)
Il seguente spezzone di codice istanzia un oggetto Date con la data corrente e la visualizza a video nel formato LONG:
1 2 3 4 |
Date d = new Date(); DateFormat formatoData = DateFormat.getDateInstance(DateFormat.LONG, Locale.ITALY); String s = formatoData.format(d); System.out.println(s); |
Nel codice dell’esempio precedente è stato sfruttato il metodo format() per convertire un oggetto di classe Date in una stringa formattata.
Il seguente programma invece istanzia un oggetto Date con la data corrente e la visualizza prima senza alcuna formattazione e poi in tutti i diversi formati messi a disposizione dalla classe DateFormat:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import java.util.Date; import java.text.DateFormat; import java.util.Locale; public class GestioneDate { public static void main(String[] args) { //vettore con le costanti degli stili disponibili int formati[] = {DateFormat.SHORT, DateFormat.MEDIUM, DateFormat.LONG, DateFormat.FULL}; //crea la data corrente Date d = new Date(); //visualizza la data non formattata (sfruttando implicitamente il metodo toString dell'oggetto) System.out.println(d); //visualizza la data nei diversi stili for(int f : formati) { //per ciascun intero f del vettore formati[] //crea l'oggetto per la conversione della data in una stringa secondo lo stile f DateFormat formatoData = DateFormat.getDateInstance(f, Locale.ITALY); String s = formatoData.format(d); System.out.println(s); } } } |
Il codice produce un output simile a questo:
Mon Mar 20 14:41:32 CET 2017
20/03/17
20-mar-2017
20 marzo 2017
lunedì 20 marzo 2017
(Procurarsi una data in input)
Il codice seguente esegue il viceversa del precedente, ossia si procura in input da tastiera una data sotto forma di stringa e la converte in un oggetto di classe Date; successivamente la stampa senza formattarla:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import java.util.*; import java.text.DateFormat; import java.text.ParseException; public class GestioneDate { public static void main(String []args){ String s; Date d = null; //si procura la data sotto forma di una stringa nel formato SHORT System.out.println("Inserisci la data [gg/mm/yyyy]: "); Scanner in = new Scanner(System.in); s = in.nextLine(); //converte la stringa della data in un oggetto di classe Date try{ DateFormat formatoData = DateFormat.getDateInstance(DateFormat.SHORT, Locale.ITALY); //imposta che i calcoli di conversione della data siano rigorosi formatoData.setLenient(false); d = formatoData.parse(s); } catch (ParseException e) { System.out.println("Formato data non valido."); } //visualizza la data non formattata (sfruttando implicitamente il metodo toString dell'oggetto) System.out.println(d); } } |
In corrispondenza di due input diversi, il codice precedente produce un output simile a questo:
- Inserisci la data [gg/mm/yyyy]:
5/8/80
Tue Aug 05 00:00:00 CEST 1980 - Inserisci la data [gg/mm/yyyy]:
5/8/1780
Sat Aug 05 00:00:00 CET 1780
Si noti la differenza tra l’interpretazione di date successive e anteriori al 1 gennaio 1970.
La classe Calendar
La classe Calendar viene introdotta qui per mostrare come effettuare delle operazioni aritmetiche su una data. Della classe Calendar prendiamo in considerazione solo i metodi che ci serviranno a questo scopo. Per approfondire lo studio di questa classe si rimanda alla documentazione del linguaggio Java presente on line (link).
Un oggetto di classe Calendar può essere istanziato a partire da un oggetto di classe Date, sfruttando il metodo statico getInstance() e il metodo setTime() della classe Calendar, nel modo seguente:
1 2 3 |
Date d = Date(); Calendar c = Calendar.getInstance(TimeZone.getTimeZone("Europe/Rome"), Locale.ITALY); c.setTime(d); |
nell’ esempio si è partiti dall’oggetto di classe Date della data corrente.
Un metodo alternativo può essere quello che sfrutta il metodo getCalendar() di un oggetto di classe DateFormat nel modo seguente:
1 2 3 4 5 6 |
Date d = new Date(); DateFormat formatoData = DateFormat.getDateInstance(DateFormat.SHORT, Locale.ITALY); //crea un oggetto di classe Calendar Calendar c = formatoData.getCalendar(); //imposta l'oggetto c alla data d c.setTime(d); |
Della classe Calendar saranno utili i seguenti metodi:
- void setTime(Date data) – imposta la data dell’oggetto di classe Calendar uguale alla data di un oggetto di classe Date fornito come parametro.
- Date getTime() – restituisce un oggetto di classe Date con la data dell’oggetto di classe Calendar su cui il metodo viene richiamato.
- void add(int campo, int quantità) – somma al campo dell’oggetto di classe Calendar, passato come primo parametro, la quantità intera passata come secondo parametro che può essere anche un intero negativo (vedi esempio sotto).
(Sommare o sottrarre ad una data un intervallo di tempo)
Con un oggetto di classe Calendar, per il quale sono definiti i valori dei campi anno, mese e giorni utilizzabili attraverso alcuni attributi statici (per approfondire consulta la documentazione del linguaggio Java: link), è possibile sommare o sottrarre alla sua data un certo intervallo di tempo nel modo seguente.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
import java.util.*; import java.text.DateFormat; import java.text.ParseException; public class GestioneDate { public static void main(String []args){ String s; Date d = null; //si procura la data sotto forma di una stringa nel formato SHORT System.out.println("Inserisci la data [gg/mm/yyyy]: "); Scanner in = new Scanner(System.in); s = in.nextLine(); try{ //converte la stringa della data in un oggetto di classe Date DateFormat formatoData = DateFormat.getDateInstance(DateFormat.SHORT, Locale.ITALY); //imposta che i calcoli di conversione della data siano rigorosi formatoData.setLenient(false); d = formatoData.parse(s); //crea un oggetto Calendar o lo imposta alla data d Calendar c = Calendar.getInstance(TimeZone.getTimeZone("Europe/Rome"), Locale.ITALY); c.setTime(d); //aggiunge 10 anni e 6 mesi alla data d c.add(Calendar.YEAR, +10); c.add(Calendar.MONTH, +6); //converte l'oggetto Calendar in una stringa nel formato SHORT e la stampa System.out.println(formatoData.format(c.getTime())); } catch (ParseException e) { System.out.println("Formato data non valido."); } } } |
Nell’esempio precedente dopo esserci procurati una data in input dalla tastiera, le abbiamo sommato 10 anni e 6 mesi e l’abbiamo visualizzata a video come stringa nel formato SHORT.
La classe SimpleDateFormat
La classe SimpleDateFormat è una classe derivata dalla classe DateFormat. Essa, quindi, eredita i metodi pubblici della superclasse, ai quali si aggiungono i propri. Questa classe rispetto alla superclasse, fornisce molta flessibilità sul formato delle date, permettendo di creare dei formati a piacere (pattern), tramite la costruzione di stringhe ottenute utilizzando combinazioni di opportune lettere. Per approfondimenti su questa classe come al solito si rimanda alla documentazione del linguaggio Java presente on line (link). Qui vedremo un semplice esempio in cui preleviamo in input da tastiera una data secondo un certo formato (pattern) da noi creato e subito dopo la visualizziamo a video in un altro formato sempre creato da noi. Il tutto è inserito all’interno di un ciclo che termina quando l’inserimento della data è andato a buon fine.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
import java.util.*; import java.text.ParseException; import java.text.SimpleDateFormat; public class GestioneDate { public static void main(String []args){ String s; do { //si procura la data sotto forma di una stringa nel formato SHORT System.out.println("Inserisci la data [gg/mm/yy HH:mm]: "); Scanner in = new Scanner(System.in); s = in.nextLine(); try{ //converte la stringa della data in un oggetto di classe Date SimpleDateFormat formato = new SimpleDateFormat("dd/MM/yy HH:mm"); Date d = formato.parse(s); //crea un oggetto 'formattatore' fissando un pattern formato = new SimpleDateFormat("'alle ore' HH:mm 'del' dd/MM/yyyy"); //visualizza la data formattata secondo il pattern fissato System.out.println("OUTPUT: " + formato.format(d)); break; //esce dal ciclo } catch (ParseException e) { System.out.println("Formato data non valido."); } } while(true); } } |
L’esecuzione del programma precedente in corrispondenza di un input valido produce a video un risultato simile al seguente:
Inserisci la data [gg/mm/yy HH:mm]:
20/03/17 9:30
OUTPUT: alle ore 09:30 del 20/03/2017