Vodič za SimpleDateFormat

1. Uvod

U ovom uputstvu uzet ćemo produbljeni obilazak SimpleDateFormat razred.

Pogledat ćemo jednostavna instancijai formatiranje stilova kao i korisne metode kojima se klasa izlaže rukovanje lokalitetima i vremenskim zonama.

2. Jednostavno primjerivanje

Prvo, pogledajmo kako napraviti instancu novog SimpleDateFormat objekt.

Postoje 4 moguća konstruktora - ali u skladu s imenom, budimo jednostavni. Sve što trebamo za početak je a Niz prikaz uzorka datuma koji želimo.

Počnimo s uzorkom datuma odvojenim crticama na sljedeći način:

"dd-MM-yyyy"

To će ispravno oblikovati datum koji započinje s tekućim danom u mjesecu, tekućim mjesecom u godini i na kraju s tekućom godinom. Naše novo oblikovanje možemo testirati jednostavnim jediničnim testom. Instancirat ćemo novi SimpleDateFormat objekt i proslijedite u poznati datum:

SimpleDateFormat formatter = novi SimpleDateFormat ("dd-MM-yyyy"); assertEquals ("24-05-1977", formatter.format (novi datum (233345223232L))); 

U gornjem kodu, oblikovač pretvara milisekunde u long na čovjeku čitljiv datum - 24. svibnja 1977.

2.1. Tvorničke metode

Iako SimpleDateFormat je zgodna klasa za brzu izradu formativača datuma, ohrabrujemo se da koristimo tvorničke metode na Oblik datuma razredgetDateFormat (), getDateTimeFormat (), getTimeFormat ().

Gornji primjer izgleda malo drugačije kada se koriste ove tvorničke metode:

DateFormat formatter = DateFormat.getDateInstance (DateFormat.SHORT); assertEquals ("5/24/77", formatter.format (novi datum (233345223232L)));

Kao što možemo vidjeti odozgo, broj mogućnosti oblikovanja unaprijed se određuje poljima na Oblik datuma razred. Ovo uglavnom ograničava naše dostupne mogućnosti formatiranja zbog čega ćemo se držati SimpleDateFormat u ovom članku.

2.2. Sigurnost navoja

JavaDoc za SimpleDateFormat izričito kaže:

Formati datuma nisu sinkronizirani. Preporučuje se stvaranje zasebnih instanci formata za svaku nit. Ako više niti istovremeno pristupa formatu, on se mora sinkronizirati izvana.

Tako SimpleDateFormat instance nisu zaštićene od niti, i trebali bismo ih pažljivo koristiti u istodobnim okruženjima.

Najbolji pristup rješavanju ovog problemaje koristiti ih u kombinaciji s a ThreadLocal. Na ovaj način svaka nit završava sa svojim SimpleDateFormat instanci, a nedostatak dijeljenja čini program sigurnim za nit:

privatni konačni ThreadLocal formatter = ThreadLocal .withInitial (() -> novi SimpleDateFormat ("dd-MM-yyyy"));

Argument za withInitial metoda je dobavljač SimpleDateFormat instance. Svaki put kad ThreadLocal treba stvoriti instancu, koristit će ovog dobavljača.

Tada možemo koristiti program za oblikovanje putem ThreadLocal primjer:

formatter.get (). format (datum)

The ThreadLocal.get () metoda inicijalizira SimpleDateFormat isprva za trenutnu nit, a zatim ponovno koristi tu instancu.

Ovu tehniku ​​nazivamo zatvaranje niti jer ograničavamo upotrebu svakog primjerka na jednu određenu nit.

Postoje dva druga pristupa rješavanju istog problema:

  • Koristeći sinkronizirano blokovi ili ReentrantLocks
  • Stvaranje bacanja primjeraka SimpleDateFormat na zahtjev

Ne preporučuju se oba ova pristupa: prvi ima značajan pogodak u izvedbi kad je prepirka velik, a drugi stvara puno predmeta, vršeći pritisak na odvozu smeća.

Vrijedno je spomenuti da, od Jave 8, novi DateTimeFormatter razred je uveden. Novi DateTimeFormatter razred je nepromjenjiv i siguran na nit. Ako radimo s Javom 8 ili novijom, koristimo novu DateTimeFormatter razred se preporučuje.

3. Datumi raščlanjivanja

SimpleDateFormat i Oblik datuma ne samo da nam omogućuju formatiranje datuma - već možemo i obrnuti postupak. Koristiti raščlaniti metodom, možemo unesite Niz prikaz datuma i vratite Datum objekt ekvivalent:

SimpleDateFormat formatter = novi SimpleDateFormat ("dd-MM-yyyy"); Datum myDate = novi datum (233276400000L); Datum parsedDate = formatter.parse ("24-05-1977"); assertEquals (myDate.getTime (), parsedDate.getTime ());

Ovdje je važno napomenuti da uzorak isporučen u konstruktoru trebao bi biti u istom formatu kao i raščlanjeni datum koristiti raščlaniti metoda.

4. Uzorci datuma i vremena

SimpleDateFormat nudi širok spektar različitih mogućnosti prilikom formatiranja datuma. Iako je puni popis dostupan u JavaDocsu, istražimo neke od najčešće korištenih opcija:

PismoKomponenta datumaPrimjer
MMjesec12; Prosinca
ggodina94
ddan23; Ponedjeljak
Hsat03
mminuta57

The izlaz koji vraća komponenta datuma također uvelike ovisi o broju upotrijebljenih znakova unutar Niz. Na primjer, uzmimo mjesec lipanj. Ako datumski niz definiramo kao:

"MM"

Tada će se naš rezultat pojaviti kao kod s brojem - 06. Međutim, ako našem datumskom nizu dodamo još M:

"MMM"

Tada se dobiva naš formatirani datum kao riječ Lipnja.

5. Primjena lokaliteta

The SimpleDateFormat razred također podržava širok raspon lokaliteta koji se postavlja kad se pozove konstruktor.

Primijenimo to u praksi oblikovanjem datuma na francuskom jeziku. Instancirat ćemo a SimpleDateFormat objekt tijekom opskrbe Lokal.FRANCIJA konstruktoru.

SimpleDateFormat franceDateFormatter = novi SimpleDateFormat ("EEEEE dd-MMMMMMM-yyyy", Locale.FRANCE); Datum myWednesday = novi datum (1539341312904L); assertTrue (franceDateFormatter.format (myWednesday) .startsWith ("vendredi"));

Davanjem određenog datuma, srijedom popodne, možemo ustvrditi da je naš franceDateFormatter je pravilno formatirao datum. Novi datum točno započinje s Vendredi -Francuski za srijedu!

Vrijedno je primijetiti malo greške u lokalnoj verziji konstruktora - iako su podržani mnogi jezici, potpuna pokrivenost nije zajamčena. Oracle preporučuje upotrebu tvorničkih metoda na Oblik datuma klase kako bi se osiguralo pokrivanje lokalizacije.

6. Promjena vremenskih zona

Od SimpleDateFormat proširuje Oblik datuma razreda, možemo i mi manipulirati vremenskom zonom pomoću setTimeZone metoda. Pogledajmo ovo na djelu:

Datum sada = novi datum (); SimpleDateFormat simpleDateFormat = novi SimpleDateFormat ("EEEE dd-MMM-yy HH: mm: ssZ"); simpleDateFormat.setTimeZone (TimeZone.getTimeZone ("Europa / London")); logger.info (simpleDateFormat.format (sada)); simpleDateFormat.setTimeZone (TimeZone.getTimeZone ("America / New_York")); logger.info (simpleDateFormat.format (sada));

U gornjem primjeru isporučujemo isto Datum na dvije različite vremenske zone na istoj SimpleDateFormat objekt. Također smo dodali Znak 'Z' do kraja uzorka Niz za označavanje razlika u vremenskim zonama. Izlaz iz format metoda se zatim zapisuje za korisnika.

Pritiskom na trčanje možemo vidjeti trenutna vremena u odnosu na dvije vremenske zone:

INFO: petak 12. listopada 18 12: 46: 14 + 0100 INFO: petak 12. listopada 18 07: 46: 14-0400

7. Sažetak

U ovom uputstvu duboko smo zarobili u zamršenost SimpleDateFormat.

Pogledali smo kako instancirati SimpleDateFormat kao i kako uzorak Niz utječe na način oblikovanja datuma.

Poigravali smo se s promjena lokaliteta izlaznog niza prije konačnog eksperimentiranja s koristeći vremenske zone.

Kao i uvijek kompletni izvorni kod možete pronaći na GitHubu.