Stando a quello che ho capito, una data può essere scritta sotto forma di
Stringa o sotto forma di
Date.
Date può prendere come parametro un numero Long che rappresenta le date a partire dall'Epoch.
L'intermediario fra Date e Stringa è SimpleDateFormat, che usa il metodo
parse() per andare da Stringa a Date, e il metodo
format() per andare da Date a Stringa.
Facciamo un po' di esercizi in tal senso...
Converto una Stringa in un Date e poi faccio l'inverso.
String stringa=("5/9/1961");
Date date=null;
DateFormat sdf=new SimpleDateFormat("dd/MM/yyyy");
try {
date=sdf.parse(stringa);
System.out.println(date.toString());
} catch (ParseException e) {
e.printStackTrace();
}
String nuovaStringa=null;
nuovaStringa=sdf.format(date);
System.out.println(nuovaStringa);
12-03 10:17:10.433 12831-12831/? I/System.out: Tue Sep 05 00:00:00 GMT+00:00 1961
12-03 10:17:10.433 12831-12831/? I/System.out: 05/09/1961
Quello che ho capito è che la reale misura del tempo è in un tipo Long, che rappresenta il numero di millisecondi dall'Epoch.
Come si estrapolano i millisecondi dall'entità Date?
Ho aggiunto una riga:
String stringa=("5/9/1961");
Date date=null;
DateFormat sdf=new SimpleDateFormat("dd/MM/yyyy");
try {
date=sdf.parse(stringa);
System.out.println(date.toString());
} catch (ParseException e) {
e.printStackTrace();
}
String nuovaStringa=null;
nuovaStringa=sdf.format(date);
System.out.println(nuovaStringa);
System.out.println(date.getTime());
12-03 11:25:32.368 13022-13022/? I/System.out: Tue Sep 05 00:00:00 GMT+00:00 1961
12-03 11:25:32.368 13022-13022/? I/System.out: 05/09/1961
12-03 11:25:32.368 13022-13022/? I/System.out: -262656000000
Mi sembra perfetto.
Ora, posso ottenere giorno mese e anno separatamente da Date?
Ho provato
String stringa=("5/9/1961");
Date date=null;
DateFormat sdf=new SimpleDateFormat("dd/MM/yyyy");
try {
date=sdf.parse(stringa);
System.out.println(date.toString());
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("weekday "+date.getDate());
System.out.println("day "+date.getDay());
System.out.println("month "+date.getMonth());
System.out.println("year "+date.getYear());
ottenendo
12-03 14:26:46.771 13504-13504/? I/System.out: Tue Sep 05 00:00:00 GMT+00:00 1961
12-03 14:26:46.771 13504-13504/? I/System.out: weekday 5
12-03 14:26:46.771 13504-13504/? I/System.out: day 2
12-03 14:26:46.794 13504-13504/? I/System.out: month 8
12-03 14:26:46.794 13504-13504/? I/System.out: year 61
e sembra che proceda tutto bene. Il mese è espresso partendo da zero, però...
SimpleDateFormat serve solo per la conversione da e a stringa.
L'unico problema è che questi metodi sono deprecati, non so perché, e come oggetto Date si consiglia adesso di usare Calendar.
Saranno deprecati ma funzionano.
Dunque posso fare tutto con l'oggetto di classe Date...
Bene. Cerco di fare un'operazione con la sottrazione di due date.
Per fare le operazioni devo ridurre tutto a millisecondi.
Posso ottenere il tempo in millisecondi mediante la funzione
Date.getTime().
Ci provo...
Sottraggo 1 ottobre 1966 da 5 settembre 1961.
Un momento!
Come ho estratto giorno, mese e anno da un oggetto di classe Date, devo essere in grado di settare questi valori.
Ricordo dei metodi precisi, anch'essi deprecati.
Si può fare sicuramente da costruttore:
Date date1=new Date(1966,10,1);
Date date2=new Date(1961,9,5);
System.out.println(date1.getMonth());
System.out.println(date2.getMonth());
12-03 14:43:46.207 13670-13670/? I/System.out: 10
12-03 14:43:46.207 13670-13670/? I/System.out: 9
Devo regolare i conti con il mese.
Per capire qualcosa, faccio una prova: immetto come mese nel costruttore di Date il numero 12, che, se il conto dei mesi inizia da zero, dovrebbe darmi un messaggio di errore in quanto il mese di Dicembre dovrebbe essere rappresentato con 11, e 12 eccederebbe il numero dei mesi.
Date date1=new Date(1966,12,1);
Date date2=new Date(1961,9,5);
System.out.println(date1.getMonth());
System.out.println(date2.getMonth());
Ed ecco:
12-03 14:50:40.126 13911-13911/? I/System.out: 0
12-03 14:50:40.126 13911-13911/? I/System.out: 9
Ottengo 0, che dovrebbe essere Gennaio...
Mi viene un dubbio: non mi avrà aggiunto un anno in più?
Prova:
Date date1=new Date(1966,12,1);
Date date2=new Date(1961,9,5);
System.out.println(date1.getMonth());
System.out.println(date1.getYear());
System.out.println(date2.getMonth());
12-03 14:52:45.347 13995-13995/? I/System.out: 0
12-03 14:52:45.347 13995-13995/? I/System.out: 1967
12-03 14:52:45.347 13995-13995/? I/System.out: 9
Infatti... mi ha aggiunto un anno in più!
Oltre che da costruttore, vediamo se si può impostare i valori di giorno, mese e anno in un oggetto di classe Date.
Date date1=new Date();
date1.setDate(5);
date1.setMonth(8);
date1.setYear(1961);
System.out.println(date1);
12-03 14:56:08.224 14083-14083/? I/System.out: Thu Sep 05 14:56:08 GMT+00:00 3861
Perfetto!
.
Ora proviamo a sottrarre le due date che avevo detto prima: la data del mio primo giorno di scuola elementare dalla data di nascita.
Date nascita=new Date(1961,8,5);
Date scuola=new Date(1966,9,1);
Long milliDiff=scuola.getTime()-nascita.getTime();
System.out.println(milliDiff);
Converto in millisecondi e faccio la sottrazione.
Ecco l'output:
12-03 14:59:47.952 14170-14170/? I/System.out: 160012800000
Ma non posso sapere a quanto tempo corrisponde quest'accozzaglia informe di millisecondi. Come faccio?
Posso andare per divisioni successive...
diviso 1000, diviso 3600 diviso 24 e ottengo i giorni... poi ci addentriamo coi bisestili e va tutto a pallino...
Proviamo con i giorni.
Date nascita=new Date(1961,8,5);
Date scuola=new Date(1966,9,1);
Long milliDiff=scuola.getTime()-nascita.getTime();
Long giorni=milliDiff/1000/3600/24;
System.out.println(giorni);
12-03 15:11:16.978 14262-14262/? I/System.out: 1852
Posso dividere per 365 e ottenere gli anni.
Date nascita=new Date(1961,8,5);
Date scuola=new Date(1966,9,1);
Long milliDiff=scuola.getTime()-nascita.getTime();
Long giorni=milliDiff/1000/3600/24/365;
System.out.println(giorni);
12-03 15:19:57.393 14669-14669/? I/System.out: 5
Ma esiste la possibilità, invece di ridurre tutto a millisecondi, di fare il calcolo direttamente fra giorni, mesi e anni?
Proviamo...
Date nascita=new Date(1961,8,5);
Date scuola=new Date(1966,9,1);
int anni=scuola.getYear()-nascita.getYear();
System.out.println(anni);
12-03 15:26:58.240 14902-14902/? I/System.out: 5
Sì, esatto. Tutto deprecato, ma tutto funzionante!
Quindi per calcolare l'età questo è perfetto!
Resta da calcolare gli anni esatti al giorno e al mese.
Ho questo schema...
Date nascita=new Date(1961,8,5);
Date scuola=new Date(1966,9,1);
int differenza=scuola.getYear()-nascita.getYear();
if(nascita.getMonth()>scuola.getMonth() ||
(nascita.getMonth()==scuola.getMonth() && nascita.getDate()>scuola.getDate())){
differenza--;
}
System.out.println(differenza);
12-03 15:34:18.835 15111-15111/? I/System.out: 5
Bene. Se invece avessi iniziato la scuola il 1 agosto 1966:
Date nascita=new Date(1961,8,5);
Date scuola=new Date(1966,7,1);
int differenza=scuola.getYear()-nascita.getYear();
if(nascita.getMonth()>scuola.getMonth() ||
(nascita.getMonth()==scuola.getMonth() && nascita.getDate()>scuola.getDate())){
differenza--;
}
System.out.println(differenza);
12-03 15:36:36.880 15192-15192/? I/System.out: 4
...avrei iniziato la scuola ancora a 5 anni non compiuti.
Se avessi iniziato il giorno prima del mio compleanno:
Date nascita=new Date(1961,8,5);
Date scuola=new Date(1966,8,4);
int differenza=scuola.getYear()-nascita.getYear();
if(nascita.getMonth()>scuola.getMonth() ||
(nascita.getMonth()==scuola.getMonth() && nascita.getDate()>scuola.getDate())){
differenza--;
}
System.out.println(differenza);
12-03 15:38:13.616 15288-15288/? I/System.out: 4
Mentre se fossi andato il giorno del mio compleanno:
Date nascita=new Date(1961,8,5);
Date scuola=new Date(1966,8,5);
int differenza=scuola.getYear()-nascita.getYear();
if(nascita.getMonth()>scuola.getMonth() ||
(nascita.getMonth()==scuola.getMonth() && nascita.getDate()>scuola.getDate())){
differenza--;
}
System.out.println(differenza);
12-03 15:39:19.222 15372-15372/? I/System.out: 5
Sarei andato a 5 anni compiuti!
Bene. Non tenendo conto delle deprecazioni, con i metodi di Date si può fare qualunque calcolo!