Lavorare con le date in Java

document_java

Lavorare con le date in Java

Vediamo alcuni utili consigli e metodologie per lavorare e manipolare al meglio le date in Java.

AGGIORNAMENTI
15/05/2012: sono stati aggiunti degli esempi su come sommare le date e come confrontare delle date

Verificare e validare le date

Vediamo come, a partire da una data in formato stringa se ne possa verificare la validità mediante un programma Java.

Problema
Abbiamo una stringa che rappresenta una data. La stringa è nel formato YYYYMMDD. Ad es. 20090115. Vogliamo verificare, mediante un programma Java, se questa stringa rappresenti una data vera e propria. Ovvero, dobbiamo verificare se i valori siano tutti numerici e in caso affermativo rappresentino effettivamente una data reale. Ad es. il valore 20090235 non rappresenta una data reale dato che il mese di febbraio non ha 35 giorni!

Soluzione: Ecco una funzione Java per fare questo.
/**
* Funzione per la verifica della corretteza di una data.
* La data di ingresso è nel formato YYYYMMDD. Questa funzione verifica che
* MM sia compreso tra 1 e 12 e che di conseguenza il giorno sia corretto.
* E' che tutti i dati siano numerici.
*
* @param testDate data da verificare nel formato stringa YYYYMMDD
* @return
*/
public boolean verifyDate(String testDate)
{
if(testDate.length()!=10)
return false;
String year = testDate.substring(0, 4);
String month = testDate.substring(4, 6);
String day = testDate.substring(6, 8);
int yearI = 0;
int monthI = 0;
int dayI = 0;
Calendar myCal = GregorianCalendar.getInstance(TimeZone.getTimeZone("Etc/UTC"));
int minMonth = myCal.getActualMinimum(Calendar.MONTH)+1;
int maxMonth = myCal.getActualMaximum(Calendar.MONTH)+1;
int minDay = 0;
int maxDay = 0;
try{
yearI = Integer.parseInt(year);
myCal.set(Calendar.YEAR, yearI);

monthI = Integer.parseInt(month);
if(!(monthI>=minMonth && monthI<=maxMonth))
return false;
myCal.set(Calendar.MONTH, monthI-1);

minDay = myCal.getActualMinimum(Calendar.DAY_OF_MONTH);
maxDay = myCal.getActualMaximum(Calendar.DAY_OF_MONTH);
dayI = Integer.parseInt(day);
if(!(dayI>=minDay && dayI<=maxDay))
return false;
myCal.set(Calendar.DAY_OF_MONTH, dayI);

}catch(NumberFormatException nfe)
{
return false;
}
return true;
}

Questa funzione Java restituisce TRUE se la verifica è andata a buon fine, FALSE altrimenti.

Formattare le date

Dato un oggetto java Date, vogliamo ottenere la data sotto forma di stringa e con un dato formalismo grafico prestabilito.


Problema
Vediamo come risolvere il problema con una funzione molto generale.
Dato un oggetto java Date, vogliamo ottenere la data sotto forma di stringa e con un dato formalismo grafico prestabilito. A volte si hanno un sacco di problemi con l'utilizzo di specifici timezone. Con la funzione proposta non ci dovrebbe essere alcun problema.

Soluzione:
Ecco il metodo da utilizzare:

java.util.Date myDate = ...oggetto date pre-esistente o creato ad hoc

//Si crea per prima cosa l'oggetto Calendar
Calendar myCal = GregorianCalendar.getInstance(TimeZone.getTimeZone("Etc/UTC"));
myCal.setTime(this.getNascita());
//Si formatta la data nella maniera voluta
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
//Si converte la data in stringa
String dataStringa = sdf.format(myCal.getTime());


Da string a Data

Data una stringa che rappresenta una data vogliamo l'oggetto date corrispondente.

Problema
A partire da una data sotto forma di stringa e con un dato formato, vogliamo controllare la stringa e ottenere un oggetto Date corrispondente.

Soluzione:
/**
* Da una stringa in formato gg/mm/aaaa restituisce una oggetto Date.
* Viene verificata anche la correttezza della stringa.
*
* @param testDate
* @return
*/
public Date stringToDate(String testDate)
{
if(testDate.length()!=10)
return null;
String day = testDate.substring(0, 2);
String month = testDate.substring(3, 5);
String year = testDate.substring(6, 10);


int yearI = 0;
int monthI = 0;
int dayI = 0;
Calendar myCal = GregorianCalendar.getInstance(TimeZone.getTimeZone("Etc/UTC"));
int minMonth = myCal.getActualMinimum(Calendar.MONTH)+1;
int maxMonth = myCal.getActualMaximum(Calendar.MONTH)+1;
int minDay = 0;
int maxDay = 0;
try{
yearI = Integer.parseInt(year);
myCal.set(Calendar.YEAR, yearI);

monthI = Integer.parseInt(month);
if(!(monthI>=minMonth && monthI<=maxMonth))
return null;
myCal.set(Calendar.MONTH, monthI-1);

minDay = myCal.getActualMinimum(Calendar.DAY_OF_MONTH);
maxDay = myCal.getActualMaximum(Calendar.DAY_OF_MONTH);
dayI = Integer.parseInt(day);
if(!(dayI>=minDay && dayI<=maxDay))
return null;
myCal.set(Calendar.DAY_OF_MONTH, dayI);

}catch(NumberFormatException nfe)
{
return null;
}
return myCal.getTime();
}


Piccola Nota
L'uso della funzione TimeZone.getTimeZone("UTC"), ovvero con il codice UTC, potrebbe generare una eccezione FileNotFoundException. I timezone di default usati da java si trovano al seguente percorso
C:\Programmi\Java\jdk1.6.0_13\jre\lib\zi

Qua dentro il file UTC non è più presente ma è presente in Etc/UTC. Quindi la maniera corrette con cui invocare la funzione è TimeZone.getTimeZone("Etc/UTC").

Confrontare le date

Vediamo come si può fare il confronto tra due date.

 

Date ora = new Date();

Calendar dataDaControllare_cal = stringToCalendar(dataDaControllareInFormatoStringa);

if(dataDaControllare_cal.getTime().before(ora))

   dataScaduta = true;


La funzione stringToCalendar è la seguente:


public static Calendar stringToCalendareHour(String testDate)
{
    testDate = testDate.trim();
    if(testDate.length()!=19)
        return null;
        String day = testDate.substring(0, 2);
        String month = testDate.substring(3, 5);
        String year = testDate.substring(6, 10);
        String hour = testDate.substring(11, 13);
        String minute = testDate.substring(14, 16);
        String second = testDate.substring(17, 19);
        
        int yearI = 0;
        int monthI = 0;
        int dayI = 0;
        int hourI = 0;
        int minuteI = 0;
        int secondI = 0;
        Calendar myCal = GregorianCalendar.getInstance();
        int minMonth = myCal.getActualMinimum(Calendar.MONTH)+1;
        int maxMonth = myCal.getActualMaximum(Calendar.MONTH)+1;
        int minDay = 0;
        int maxDay = 0;
        try{
            yearI = Integer.parseInt(year);
            myCal.set(Calendar.YEAR, yearI);

            monthI = Integer.parseInt(month);
            if(!(monthI>=minMonth && monthI<=maxMonth))
                return null;
            myCal.set(Calendar.MONTH, monthI-1);

            minDay = myCal.getActualMinimum(Calendar.DAY_OF_MONTH);
            maxDay = myCal.getActualMaximum(Calendar.DAY_OF_MONTH);
            dayI = Integer.parseInt(day);
            if(!(dayI>=minDay && dayI<=maxDay))
                return null;
            myCal.set(Calendar.DAY_OF_MONTH, dayI);
            
            hourI = Integer.parseInt(hour);
            if( !(hourI>=0 && hourI<=24) )
                return null;
            myCal.set(Calendar.HOUR_OF_DAY, hourI);
            
            minuteI = Integer.parseInt(minute);
            if( !(minuteI>=0 && minuteI<=60) )
                return null;
            myCal.set(Calendar.MINUTE, minuteI);
            
            secondI = Integer.parseInt(second);
            if( !(secondI>=0 && secondI<=60) )
                return null;
            myCal.set(Calendar.SECOND, secondI);
            
            myCal.set(Calendar.MILLISECOND, 0);
            
        }catch(NumberFormatException nfe)
        {
            //Va gestito un eventuale errore
            return null;
        }
        return myCal;
}

 

Fare le somme con le date

Vediamo come si possono sommare due mesi ad una data:

 

Calendar dataDaControllare_cal = stringToCalendar(dataDaControllareInFormatoStringa);
dataDaControllare_cal.add(Calendar.MONTH, 2);   

 

Come si possono sommare 10 giorni?

 

Calendar dataDaControllare_cal = stringToCalendar(dataDaControllareInFormatoStringa);
dataDaControllare_cal.add(Calendar.DAY_OF_MONTH, 10);   

 

Come si possono sottrarre 10 giorni?

Calendar dataDaControllare_cal = stringToCalendar(dataDaControllareInFormatoStringa);
dataDaControllare_cal.add(Calendar.DAY_OF_MONTH, -10);   


Buon lavoro!