En guide til SimpleDateFormat

1. Introduktion

I denne vejledning tager vi en dybtgående rundvisning i SimpleDateFormat klasse.

Vi kigger på enkel instantieringog formatering af stilarter såvel som nyttige metoder, som klassen udsætter for håndtering af lokaliteter og tidszoner.

2. Enkel instantiering

Lad os først se på, hvordan man starter et nyt SimpleDateFormat objekt.

Der er 4 mulige konstruktører - men i overensstemmelse med navnet, lad os holde tingene enkle. Alt, hvad vi har brug for for at komme i gang, er en Snor repræsentation af et datomønster, vi ønsker.

Lad os starte med et dash-adskilt datomønster som sådan:

"dd-MM-åååå"

Dette formaterer korrekt en dato, der starter med den aktuelle dag i måneden, den aktuelle måned i året og endelig det aktuelle år. Vi kan teste vores nye formater med en simpel enhedstest. Vi starter et nyt SimpleDateFormat gøre indsigelse og videregive en kendt dato:

SimpleDateFormat formatter = ny SimpleDateFormat ("dd-MM-åååå"); assertEquals ("24-05-1977", formatter.format (ny dato (233345223232L))); 

I ovenstående kode er formatering konverterer millisekunder som long ind i en menneskelig læsbar dato - den 24. maj 1977.

2.1. Fabriksmetoder

Selvom SimpleDateFormat er en praktisk klasse til hurtigt at oprette en datoformatering, Vi opfordres til at bruge fabriksmetoderne på Datoformat klassegetDateFormat (), getDateTimeFormat (), getTimeFormat ().

Ovenstående eksempel ser lidt anderledes ud, når du bruger disse fabriksmetoder:

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

Som vi kan se ovenfra, bestemmes antallet af formateringsmuligheder forud af felterne på Datoformat klasse. Dette stort set begrænser vores tilgængelige muligheder for formatering Derfor holder vi os til SimpleDateFormat i denne artikel.

2.2. Trådsikkerhed

JavaDoc til SimpleDateFormat udtrykkeligt siger:

Datoformater synkroniseres ikke. Det anbefales at oprette separate formatforekomster for hver tråd. Hvis flere tråde får adgang til et format samtidigt, skal det synkroniseres eksternt.

SimpleDateFormat tilfælde er ikke trådsikre, og vi skal bruge dem omhyggeligt i samtidige miljøer.

Den bedste metode til at løse dette problemer at bruge dem i kombination med en Trådlokal. På denne måde ender hver tråd med sin egen SimpleDateFormat eksempel, og manglen på deling gør programmet trådsikkert:

privat endelig ThreadLocal formatter = ThreadLocal .withInitial (() -> ny SimpleDateFormat ("dd-MM-åååå"));

Argumentet for med Initial metoden er en leverandør af SimpleDateFormat tilfælde. Hver gang Trådlokal har brug for at oprette en instans, bruger den denne leverandør.

Så kan vi bruge formateringen via Trådlokal eksempel:

formatter.get (). format (dato)

Det ThreadLocal.get () metoden initialiserer SimpleDateFormat til den aktuelle tråd først og genbruger derefter den forekomst.

Vi kalder denne teknik trådindeslutning når vi begrænser brugen af ​​hver forekomst til en bestemt tråd.

Der er to andre tilgange til at tackle det samme problem:

  • Ved brug af synkroniseret blokke eller ReentrantLocks
  • Oprette smid forekomster af SimpleDateFormat on-demand

Begge disse tilgange anbefales ikke: Førstnævnte får et betydeligt præstationshit, når påstanden er høj, og sidstnævnte skaber mange objekter og lægger pres på affaldsopsamling.

Det er værd at nævne det, siden Java 8, en ny DateTimeFormatter klasse er blevet introduceret. Den nye DateTimeFormatter klasse er uforanderlig og trådsikker. Hvis vi arbejder med Java 8 eller nyere, bruger vi det nye DateTimeFormatter klasse anbefales.

3. Parsedatoer

SimpleDateFormat og Datoformat ikke kun tillade os at formatere datoer - men vi kan også vende operationen. Bruger parse metode, kan vi indtast Snor repræsentation af en dato og returnere Dato objektækvivalent:

SimpleDateFormat formatter = ny SimpleDateFormat ("dd-MM-åååå"); Dato myDate = ny dato (233276400000L); Dato parsedDate = formatter.parse ("24-05-1977"); assertEquals (myDate.getTime (), parsedDate.getTime ());

Det er vigtigt at bemærke her, at mønster leveret i konstruktøren skal være i samme format som den dato, der blev analyseret bruger parse metode.

4. Dato-tid mønstre

SimpleDateFormat leverer en lang række forskellige muligheder ved formatering af datoer. Mens den fulde liste er tilgængelig i JavaDocs, lad os undersøge nogle af de mere almindeligt anvendte muligheder:

BrevDatokomponentEksempel
MMåned12; Dec
yår94
ddag23; Man
Htime03
mminut57

Det output, der returneres af datokomponenten, afhænger også stærkt af antallet af anvendte tegn indenfor Snor. Lad os for eksempel tage juni måned. Hvis vi definerer datostrengen som:

"MM"

Så vises vores resultat som nummerkoden - 06. Hvis vi dog tilføjer en anden M til vores datostreng:

"MMM"

Derefter vises vores resulterende formaterede dato som ordet Jun.

5. Anvendelse af lokaliteter

Det SimpleDateFormat klasse også understøtter en bred vifte af lokaliteter som indstilles, når konstruktøren kaldes.

Lad os implementere dette ved at formatere en dato på fransk. Vi instantierer en SimpleDateFormat genstand under levering Landestandard. FRANKRIG til konstruktøren.

SimpleDateFormat franceDateFormatter = ny SimpleDateFormat ("EEEEE dd-MMMMMMM-åååå", Locale.FRANCE); Dato myWednesday = ny dato (1539341312904L); assertTrue (franceDateFormatter.format (myWednesday) .startsWith ("vendredi"));

Ved at angive en given dato, onsdag eftermiddag, kan vi hævde, at vores franceDateFormatter har formateret datoen korrekt. Den nye dato starter korrekt med Vendredi -Fransk til onsdag!

Det er værd at bemærke lidt gotcha i den lokale version af konstruktøren - mens mange lokaliteter understøttes, er fuld dækning ikke garanteret. Oracle anbefaler at bruge fabriksmetoderne til Datoformat klasse for at sikre lokal dækning.

6. Ændring af tidszoner

Siden SimpleDateFormat udvider Datoformat klasse, kan vi også manipulere tidszonen ved hjælp af setTimeZone metode. Lad os se på dette i aktion:

Dato nu = ny dato (); SimpleDateFormat simpleDateFormat = ny SimpleDateFormat ("EEEE dd-MMM-åå HH: mm: ssZ"); simpleDateFormat.setTimeZone (TimeZone.getTimeZone ("Europa / London")); logger.info (simpleDateFormat.format (nu)); simpleDateFormat.setTimeZone (TimeZone.getTimeZone ("America / New_York")); logger.info (simpleDateFormat.format (nu));

I ovenstående eksempel leverer vi det samme Dato til to forskellige tidszoner på samme SimpleDateFormat objekt. Vi har også tilføjet 'Z' karakter til slutningen af ​​mønsteret Snor for at angive tidszoneforskellene. Outputtet fra format metoden logges derefter for brugeren.

Når vi rammer, kan vi se de aktuelle tider i forhold til de to tidszoner:

INFO: Fredag ​​12-okt-18 12: 46: 14 + 0100 INFO: Fredag ​​12-oktober-18 07: 46: 14-0400

7. Resume

I denne vejledning har vi taget et dybt dyk i indviklingen af SimpleDateFormat.

Vi har set på, hvordan vi gør det øjeblikkelig SimpleDateFormat samt hvordan mønster Snor påvirker, hvordan datoen formateres.

Vi spillede med ændre lokaliteter af output String før endelig eksperimenterer med ved hjælp af tidszoner.

Som altid kan den komplette kildekode findes på GitHub.