public class Main {
public static void main(String[] args) {
String date = "June 11, 2018";
System.out.println(date);
}
}
Ma questo approccio presenta molti svantaggi. La classe String
è stata creata per funzionare con il testo e dispone di metodi appropriati. Se dobbiamo in qualche modo gestire la data (aggiungervi 2 ore, ad esempio), String
qui non funzionerà. Oppure, ad esempio, visualizzare la data e l'ora attuali nel momento in cui il programma è stato compilato nella console. QuiString
: mentre scrivi il codice e lo esegui, l'ora cambierà e l'irrilevante verrà visualizzato nella console. Pertanto, in Java, i suoi creatori hanno fornito diverse classi per lavorare con date e orari. Il primo è la classejava.util.Date
Classe di date Java
Gli abbiamo dato il nome completo perché esiste anche una classe in un altro pacchetto in Javajava.sql.Date
. Non confonderti! La prima cosa che devi sapere è che memorizza la data in millisecondi trascorsi dal 1 gennaio 1970. C'è anche un nome separato per questa data: "Unix time". Un modo piuttosto interessante, non sei d'accordo? :) La seconda cosa da ricordare: se crei un oggetto Date
con un costruttore vuoto, il risultato sarà la data e l'ora correnti al momento della creazione dell'oggetto . String
Ricordi come abbiamo scritto che un'attività del genere sarebbe problematica per un formato di data ? La classe Date
lo risolve facilmente.
public class Main {
public static void main(String[] args) {
Date date = new Date();
System.out.println(date);
}
}
Esegui questo codice più volte e vedrai come cambierà l'ora ogni volta :) Questo è possibile proprio perché è memorizzato in millisecondi: sono l'unità di tempo più piccola, motivo per cui i risultati sono così accurati. Esiste un altro costruttore per Date
: puoi specificare il numero esatto di millisecondi trascorsi dalle 00:00 del 1 gennaio 1970 alla data richiesta e verrà creato:
public class Main {
public static void main(String[] args) {
Date date = new Date(1212121212121L);
System.out.println(date);
}
}
Uscita console:
Fri May 30 08:20:12 MSD 2008
L'abbiamo ottenuto il 30 maggio 2008. "Ven" indica il giorno della settimana - "Venerdì" (venerdì) e MSD - "Ora legale di Mosca" (ora legale di Mosca). I millisecondi vengono trasmessi nel formato long
, poiché il loro numero molto spesso non rientra nel formato int
. Quindi, di che tipo di operazioni sulla data potremmo aver bisogno nel nostro lavoro? Ebbene, la cosa più ovvia, ovviamente, è il confronto . Determina se una data è successiva o precedente a un'altra. Questo può essere fatto in diversi modi. Ad esempio, puoi chiamare il metodo . Date.getTime()
, che restituirà il numero di millisecondi trascorsi dalla mezzanotte del 1 gennaio 1970. Chiamiamolo semplicemente su due oggetti Date e confrontiamoli tra loro:
public class Main {
public static void main(String[] args) {
Date date1 = new Date();
Date date2 = new Date();
System.out.println((date1.getTime() > date2.getTime())?
"date1 is later than date2" : "date1 is earlier than date2");
}
}
Conclusione:
date1 раньше date2
Ma esiste un modo più conveniente, ovvero utilizzare metodi speciali della classe Date
: before()
, after()
e equals()
. Tutti restituiscono il risultato in formato boolean
. Il metodo before()
controlla se la nostra data è precedente a quella che passiamo come argomento:
public class Main {
public static void main(String[] args) throws InterruptedException {
Date date1 = new Date();
Thread.sleep(2000);//pause the program for 2 seconds
Date date2 = new Date();
System.out.println(date1.before(date2));
}
}
Uscita console:
true
Il metodo funziona in modo simile after()
; controlla se la nostra data è successiva a quella che passiamo come argomento:
public class Main {
public static void main(String[] args) throws InterruptedException {
Date date1 = new Date();
Thread.sleep(2000);//pause the program for 2 seconds
Date date2 = new Date();
System.out.println(date1.after(date2));
}
}
Uscita console:
false
Nei nostri esempi, mettiamo il programma in pausa per 2 secondi in modo che le due date siano sicuramente diverse. Sui computer veloci, il tempo tra la creazione date1
e date2
può essere inferiore a un millisecondo, nel qual caso entrambi e before()
e after()
restituiranno false
. Ma il metodo equals()
in una situazione del genere tornerà true
! Dopotutto, confronta esattamente il numero di millisecondi trascorsi dalle 00:00 del 1 gennaio 1970 per ciascuna data. Gli oggetti verranno considerati uguali solo se corrispondono al millisecondo:
public static void main(String[] args) {
Date date1 = new Date();
Date date2 = new Date();
System.out.println(date1.getTime());
System.out.println(date2.getTime());
System.out.println(date1.equals(date2));
}
Ecco qualcos'altro a cui devi prestare attenzione. Se apri la documentazione della classe Date
sul sito Web di Oracle, vedrai che molti dei suoi metodi e costruttori sono stati designati come Deprecated
("deprecati"). Ecco, guarda: Data della classe Ecco cosa dicono gli stessi creatori di Java riguardo quelle parti delle classi che sono diventate deprecate: “Un elemento di programma annotato con @Deprecated è qualcosa che i programmatori sono scoraggiati dall'utilizzare, solitamente perché è pericoloso, o perché c’è un’alternativa migliore.” Ciò non significa che questi metodi non possano essere utilizzati affatto. Inoltre, se provi tu stesso a eseguire il codice utilizzandoli in IDEA, molto probabilmente funzionerà, prendiamo ad esempio il metodo deprecato Date.getHours()
, che restituisce il numero di ore dall'oggetto Date
.
public static void main(String[] args) {
Date date1 = new Date();
System.out.println(date1.getHours());
}
Se all'ora in cui esegui il codice, ad esempio, sono le 14:21, verrà visualizzato il numero 14. Come puoi vedere, il metodo deprecato è barrato, ma funziona abbastanza bene. Questi metodi non sono stati rimossi completamente, per non danneggiare un mucchio di codice già scritto utilizzandoli. Cioè, questi metodi non sono "rotti" o "rimossi", semplicemente non sono consigliati per l'uso a causa della disponibilità di un'alternativa più conveniente. A proposito, è scritto proprio nella documentazione: la maggior parte dei metodi della classe Date sono stati spostati nella sua versione migliorata ed estesa: la classe Calendar
. Lo conosceremo meglio :)
Calendario Java
Java 1.1 ha introdotto una nuova classe -Calendar
. Ha reso il lavoro con le date in Java un po' più semplice di quanto sembrasse prima. L'unica implementazione della classe Calendar
con cui lavoreremo è la classe GregorianCalendar
(implementa il calendario gregoriano, secondo il quale vive la maggior parte dei paesi del mondo). La sua principale comodità è che può funzionare con le date in un formato più conveniente. Ad esempio, può:
- Aggiungi un mese o un giorno alla data corrente
- Controlla se l'anno è bisestile;
- Ottieni singoli componenti della data (ad esempio, ottieni il numero del mese da una data intera)
- Inoltre, al suo interno è stato sviluppato un sistema di costanti molto comodo (ne vedremo molte di seguito).
Calendar
è che implementa una costante Calendar.Era
: è possibile impostare la data sull'era AC (“Prima di Cristo” - prima della nascita di Cristo, cioè “prima della nostra era”) o AC (“Dopo Cristo” - “ nostra epoca"). Diamo un'occhiata a tutto questo con esempi. Creiamo un calendario con la data 25 gennaio 2017:
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar(2017, 0 , 25);
}
I mesi nella classe Calendar
(come in Date
, tra l'altro) iniziano da zero, quindi abbiamo passato il numero 0 come secondo argomento. La cosa principale quando si lavora con una classe Calendar
è capire che si tratta di un calendario e non di una data separata. Una data è semplicemente una serie di numeri che rappresentano uno specifico periodo di tempo. E un calendario è un intero dispositivo con il quale puoi fare molte cose con le date :) Questo può essere visto abbastanza chiaramente se provi a inviare l'oggetto Calendario alla console: Output:
java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Moscow",offset=10800000,dstSavings=0,useDaylight=false,transitions=79,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=1,ERA=?,YEAR=2017,MONTH=0,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_MONTH=25,DAY_OF_YEAR=?,DAY_OF_WEEK=?,DAY_OF_WEEK_IN_MONTH=?,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?]
Guarda quante informazioni ci sono! Il calendario ha un sacco di proprietà che una data normale non ha e tutte vengono inviate alla console (questo è il modo in cui funziona il metodo toString()
nella classe Calendar
). Se, mentre lavori, hai solo bisogno di ottenere una semplice data dal calendario, ad es. oggetto Date
: questo viene fatto utilizzando un metodo Calendar.getTime()
(il nome non è il più logico, ma non si può fare nulla):
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar(2017, 0 , 25);
Date date = calendar.getTime();
System.out.println(date);
}
Conclusione:
Wed Jan 25 00:00:00 MSK 2017
Ora abbiamo “semplificato” il calendario trasformandolo in una data normale. Andiamo avanti. Oltre ai simboli numerici per i mesi, Calendar
in classe è possibile utilizzare le costanti. Le costanti sono campi statici di una classe Calendar
con un valore già impostato che non può essere modificato. Questa opzione è in realtà migliore, poiché migliora la leggibilità del codice.
public static void main(String[] args) {
GregorianCalendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
}
Calendar.JANUARY
— una delle costanti per indicare il mese. Con questa opzione di denominazione, nessuno dimenticherà, ad esempio, che il numero "3" significa aprile e non il terzo mese a cui siamo abituati: marzo. Basta scrivere Calendar.APRIL
e il gioco è fatto :) Tutti i campi del calendario (giorno, mese, minuti, secondi, ecc.) possono essere impostati individualmente utilizzando il metodo set()
. È molto conveniente, poiché Calendar
ogni campo ha la propria costante nella classe e il codice finale apparirà il più semplice possibile. Ad esempio, nell'esempio precedente, abbiamo creato una data, ma non abbiamo impostato l'ora corrente. Impostiamo l'ora alle 19:42:12
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar();
calendar.set(Calendar.YEAR, 2017);
calendar.set(Calendar.MONTH, 0);
calendar.set(Calendar.DAY_OF_MONTH, 25);
calendar.set(Calendar.HOUR_OF_DAY, 19);
calendar.set(Calendar.MINUTE, 42);
calendar.set(Calendar.SECOND, 12);
System.out.println(calendar.getTime());
}
Conclusione:
Wed Jan 25 19:42:12 MSK 2017
Chiamiamo il metodo set()
, gli passiamo una costante (a seconda del campo che vogliamo modificare) e un nuovo valore per questo campo. Si scopre che il metodo set()
è una sorta di "super-setter" che può impostare un valore non per un campo, ma per molti campi :) L'aggiunta e la sottrazione di valori in una classe Calendar
vengono eseguite utilizzando il metodo add()
. Devi passarci il campo che vuoi modificare e il numero, esattamente quanto vuoi aggiungere/sottrarre dal valore corrente. Ad esempio, impostiamo la data di creazione su 2 mesi fa:
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
calendar.set(Calendar.HOUR, 19);
calendar.set(Calendar.MINUTE, 42);
calendar.set(Calendar.SECOND, 12);
calendar.add(Calendar.MONTH, -2);//to subtract a value - a negative number must be passed to the method
System.out.println(calendar.getTime());
}
Conclusione:
Fri Nov 25 19:42:12 MSK 2016
Grande! Abbiamo fissato la data a 2 mesi fa. Di conseguenza, non solo il mese, ma anche l'anno è cambiato, dal 2017 al 2016. Il calcolo dell'anno corrente quando si spostano le date, ovviamente, viene eseguito automaticamente e non è necessario controllarlo manualmente. Ma se per qualche scopo hai bisogno di disabilitare questo comportamento, puoi farlo. Un metodo speciale roll()
può aggiungere e sottrarre valori senza influenzare altri valori. Ad esempio, in questo modo:
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
calendar.set(Calendar.HOUR, 10);
calendar.set(Calendar.MINUTE, 42);
calendar.set(Calendar.SECOND, 12);
calendar.roll(Calendar.MONTH, -2);
System.out.println(calendar.getTime());
}
Abbiamo fatto esattamente la stessa cosa dell'esempio precedente: abbiamo sottratto 2 mesi dalla data corrente. Ma ora il codice funzionava diversamente: il mese cambiava da gennaio a novembre, ma l’anno rimaneva lo stesso del 2017! Conclusione:
Sat Nov 25 10:42:12 MSK 2017
Ulteriore. Come abbiamo detto sopra, tutti i campi di un oggetto Calendar
possono essere ottenuti separatamente. Il metodo è responsabile di questo get()
:
public static void main(String[] args) {
GregorianCalendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
calendar.set(Calendar.HOUR, 10);
calendar.set(Calendar.MINUTE, 42);
calendar.set(Calendar.SECOND, 12);
System.out.println("Year: " + calendar.get(Calendar.YEAR));
System.out.println("Month: " + calendar.get(Calendar.MONTH));
System.out.println("Number of the week in the month: " + calendar.get(Calendar.WEEK_OF_MONTH));// serial number of the week in the month
System.out.println("Number: " + calendar.get(Calendar.DAY_OF_MONTH));
System.out.println("Watch: " + calendar.get(Calendar.HOUR));
System.out.println("Minutes: " + calendar.get(Calendar.MINUTE));
System.out.println("Seconds: " + calendar.get(Calendar.SECOND));
System.out.println("Milliseconds: " + calendar.get(Calendar.MILLISECOND));
}
Conclusione:
Год: 2017
Месяц: 0
Порядковый номер недели в месяце: 4
Число: 25
Часы: 10
Минуты: 42
Секунды: 12
Миллисекунды: 0
Cioè, oltre al "super-setter" nella classe Calendar
c'è anche un "super-getter" :) Un altro punto interessante è, ovviamente, lavorare con le ere. Per creare una data “a.C.” è necessario utilizzare il campo Calendar.Era
Ad esempio, creiamo una data che indichi la Battaglia di Canne, in cui Annibale sconfisse l'esercito di Roma. Ciò accadde il 2 agosto 216 a.C. e.:
public static void main(String[] args) {
GregorianCalendar cannes = new GregorianCalendar(216, Calendar.AUGUST, 2);
cannes.set(Calendar.ERA, GregorianCalendar.BC);
DateFormat df = new SimpleDateFormat("dd MMM yyy GG");
System.out.println(df.format(cannes.getTime()));
}
Qui abbiamo utilizzato la classe SimpleDateFormat
per visualizzare la data in un formato per noi più comprensibile (le lettere “GG” sono responsabili della visualizzazione dell'era). Conclusione:
02 авг 216 до н.э.
Calendar
Ci sono molti altri metodi e costanti nella classe , leggili nella documentazione:
Nuova riga fino ad oggi
Per convertire String in Date, puoi utilizzare la classe helper Java - SimpleDateFormat . Questa è la classe necessaria per convertire una data in un formato da te definito. A sua volta, è molto simile a DateFormat . L'unica differenza degna di nota tra i due è che SimpleDateFormat può essere utilizzato per la formattazione (conversione di una data in una stringa) e l'analisi della stringa in una data compatibile con le impostazioni locali, mentre DateFormat non supporta le impostazioni locali. Inoltre, DateFormat è una classe astratta che fornisce il supporto di base per la formattazione e l'analisi delle date, mentre SimpleDateFormat è una classe concreta che estende la classe DateFormat. Ecco come appare un esempio di creazione di un oggetto SimpleDateFormat e formattazione di una data:SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date(1212121212121L);
System.out.println(formatter.format(date));
Nell'esempio sopra abbiamo utilizzato il modello "aaaa-MM-gg HH:mm:ss" che significa:
- 4 cifre per l'anno (aaaa);
- 2 cifre per il mese (MM);
- 2 cifre per il giorno (dd);
- 2 cifre per le ore nel formato 24 ore (HH);
- 2 cifre per i minuti (mm);
- 2 cifre per i secondi (ss).
2008-05-30 08:20:12
Sono disponibili numerose lettere modello per la classe SimpleDateFormat . Per non farti confondere, li abbiamo raccolti in una tabella:
Simbolo | Descrizione | Esempio |
---|---|---|
G | era (nella localizzazione inglese - d.C. e a.C.) | ANNO DOMINI |
sì | anno (numero a 4 cifre) | 2020 |
aa | anno (ultime 2 cifre) | 20 |
aaaa | anno (numero a 4 cifre) | 2020 |
M | numero del mese (senza zeri iniziali) | 8 |
MM | numero del mese (con zeri iniziali se il numero del mese è < 10) | 04 |
MMM | abbreviazione del mese di tre lettere (secondo la localizzazione) | Gen |
MMMM | nome completo del mese | Giugno |
w | settimana dell'anno (senza zeri iniziali) | 4 |
ww | settimana dell'anno (con zeri iniziali) | 04 |
W | settimana nel mese (senza zeri iniziali) | 3 |
WW | settimana nel mese (con zero iniziale) | 03 |
D | giorno dell'anno | 67 |
D | giorno del mese (senza zeri iniziali) | 9 |
gg | giorno del mese (con zeri iniziali) | 09 |
F | giorno della settimana del mese (senza zeri iniziali) | 9 |
FF | giorno della settimana del mese (con zeri iniziali) | 09 |
E | giorno della settimana (abbreviazione) | W |
EEEE | giorno della settimana (completo) | Venerdì |
tu | numero del giorno della settimana (senza zeri iniziali) | 5 |
uu | numero del giorno della settimana (con zeri iniziali) | 05 |
UN | Indicatore AM/PM | SONO. |
H | ore nel formato 24 ore senza zeri iniziali | 6 |
HH | orologio nel formato 24 ore con zero iniziale | 06 |
K | numero di ore nel formato 24 ore | 18 |
K | numero di ore nel formato 12 ore | 6 |
H | l'ora nel formato 12 ore senza zeri iniziali | 6 |
eh | ora nel formato 12 ore con zero iniziale | 06 |
M | minuti senza zeri iniziali | 32 |
mm | minuti con zero iniziale | 32 |
S | secondi senza zeri iniziali | undici |
ss | secondi con zero iniziale | undici |
S | millisecondi | 297 |
z | Fuso orario | EET |
Z | fuso orario nel formato RFC 822 | 300 |
Campione | Esempio |
---|---|
gg-MM-aaaa | 01-11-2020 |
aaaa-MM-gg | 2019-10-01 |
HH:mm:ss.SSS | 23:59.59.999 |
aaaa-MM-gg HH:mm:ss | 2018-11-30 03:09:02 |
aaaa-MM-gg HH:mm:ss.SSS | 2016-03-01 01:20:47.999 |
aaaa-MM-gg HH:mm:ss.SSS Z | 2013-13-13 23:59:59.999 +0100 |
-
Crea una riga da cui devi impostare la data:
String strDate = "Sat, April 4, 2020";
-
Creiamo un nuovo oggetto SimpleDateFormat con un template che corrisponda a quello che abbiamo nella stringa (altrimenti non saremo in grado di analizzarlo):
SimpleDateFormat formatter = new SimpleDateFormat("EEE, MMMM d, yyyy", Locale.ENGLISH);
Come puoi vedere, qui abbiamo un argomento Locale. Se lo omettiamo, utilizzerà la Locale predefinita, che non è sempre l'inglese.
Se la locale non corrisponde alla stringa di input, i dati della stringa associati alla lingua, come la nostra Mon o April , non verranno riconosciuti e genereranno una java.text.ParseException, anche se il modello corrisponde.
Tuttavia, non dobbiamo specificare il formato se utilizziamo un modello che non è specifico della lingua. Ad esempio: aaaa-MM-gg HH:mm:ss
-
Creiamo una data utilizzando un formattatore, che a sua volta la analizza dalla stringa di input:
try { Date date = formatter.parse(strDate); System.out.println(date); } catch (ParseException e) { e.printStackTrace(); }
Uscita console:
Sat Apr 04 00:00:00 EEST 2020
Hmmm... Ma il formato non è più lo stesso!
Per creare lo stesso formato, utilizziamo nuovamente il formattatore:
System.out.println(formatter.format(date));
Uscita console:
Sat, April 4, 2020
SimpleDateFormat e calendario
SimpleDateFormat ti consente di formattare tutti gli oggetti Data e Calendario creati per un uso successivo. Consideriamo un punto così interessante come lavorare con le epoche. Per creare una data “AC” è necessario utilizzare il campo Calendar.Era. Ad esempio, creiamo una data che indichi la battaglia di Canne, in cui Annibale sconfisse l'esercito di Roma. Ciò accadde il 2 agosto 216 a.C. e.:public static void main(String[] args) {
GregorianCalendar cannes = new GregorianCalendar(216, Calendar.AUGUST, 2);
cannes.set(Calendar.ERA, GregorianCalendar.BC);
DateFormat df = new SimpleDateFormat("dd MMM yyy GG");
System.out.println(df.format(cannes.getTime()));
}
Qui abbiamo utilizzato la classe SimpleDateFormat per visualizzare la data in un formato per noi più comprensibile (come indicato sopra, le lettere "GG" sono responsabili della visualizzazione dell'era). Conclusione:
02 авг 216 до н.э.
Formato data Java
Ecco un altro caso. Supponiamo che questo formato di data non sia adatto a noi:
Sat Nov 25 10:42:12 MSK 2017
Quindi eccolo qui. Utilizzando le nostre funzionalità nel formato data Java, puoi modificarlo nel tuo senza troppe difficoltà:
public static void main(String[] args) {
SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE, d MMMM yyyy");
Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
calendar.set(Calendar.HOUR, 10);
calendar.set(Calendar.MINUTE, 42);
calendar.set(Calendar.SECOND, 12);
calendar.roll(Calendar.MONTH, -2);
System.out.println(dateFormat.format(calendar.getTime()));
}
Conclusione:
суббота, 25 Ноябрь 2017
Molto meglio, vero? :)
GO TO FULL VERSION