Een gids voor SimpleDateFormat

1. Inleiding

In deze tutorial nemen we een diepgaande rondleiding door de SimpleDateFormat klasse.

We zullen er naar kijken eenvoudige instantiatieen opmaakstijlen evenals nuttige methoden waarvoor de klasse zich presenteert omgaan met landinstellingen en tijdzones.

2. Eenvoudige instantiatie

Laten we eerst eens kijken hoe we een nieuwe instantiëren SimpleDateFormat voorwerp.

Er zijn 4 mogelijke constructeurs - maar laten we, in overeenstemming met de naam, de dingen simpel houden. Alles wat we nodig hebben om te beginnen is een Draad weergave van een datumpatroon dat we willen.

Laten we beginnen met een datumpatroon met streepjes als volgt:

"dd-MM-jjjj"

Hierdoor wordt een datum correct opgemaakt, beginnend met de huidige dag van de maand, de huidige maand van het jaar en tenslotte het huidige jaar. We kunnen onze nieuwe formatter testen met een simpele unit test. We zullen een nieuwe instantiëren SimpleDateFormat bezwaar maken en een bekende datum doorgeven:

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

In de bovenstaande code, de formatter converteert milliseconden naar long in een voor mensen leesbare datum - 24 mei 1977.

2.1. Fabrieksmethoden

Hoewel SimpleDateFormat is een handige klasse om snel een datumnotatie te bouwen, we worden aangemoedigd om de fabrieksmethoden op de Datumnotatie klassegetDateFormat (), getDateTimeFormat (), getTimeFormat ().

Het bovenstaande voorbeeld ziet er een beetje anders uit bij het gebruik van deze fabrieksmethoden:

DateFormat-formatter = DateFormat.getDateInstance (DateFormat.SHORT); assertEquals ("5/24/77", formatter.format (new Date (233345223232L)));

Zoals we hierboven kunnen zien, wordt het aantal opmaakopties vooraf bepaald door de velden op het Datumnotatie klasse. Dit grotendeels beperkt onze beschikbare opties voor opmaak daarom houden we ons aan SimpleDateFormat in dit artikel.

2.2. Draad-veiligheid

De JavaDoc voor SimpleDateFormat stelt expliciet:

Datumnotaties worden niet gesynchroniseerd. Het wordt aanbevolen om voor elke thread afzonderlijke indelingsinstanties te maken. Als meerdere threads gelijktijdig toegang hebben tot een indeling, moet deze extern worden gesynchroniseerd.

Zo SimpleDateFormat instanties zijn niet thread-safe, en we moeten ze zorgvuldig gebruiken in gelijktijdige omgevingen.

De beste aanpak om dit probleem op te lossenis om ze te gebruiken in combinatie met een ThreadLocal. Op deze manier krijgt elke draad zijn eigen SimpleDateFormat bijvoorbeeld, en het gebrek aan delen maakt het programma thread-safe:

private laatste ThreadLocal-formatter = ThreadLocal .withInitial (() -> nieuwe SimpleDateFormat ("dd-MM-jjjj"));

Het argument voor de withInitial method is leverancier van SimpleDateFormat gevallen. Elke keer dat de ThreadLocal een instantie moet maken, wordt deze leverancier gebruikt.

Dan kunnen we de formatter gebruiken via de ThreadLocal voorbeeld:

formatter.get (). format (datum)

De ThreadLocal.get () methode initialiseert het SimpleDateFormat eerst voor de huidige thread en vervolgens die instantie opnieuw gebruiken.

We noemen deze techniek draad opsluiting aangezien we het gebruik van elke instantie beperken tot één specifieke thread.

Er zijn twee andere benaderingen om hetzelfde probleem aan te pakken:

  • Gebruik makend van gesynchroniseerd blokken of ReentrantLocks
  • Het creëren van wegwerpinstanties van SimpleDateFormat op aanvraag

Beide benaderingen worden niet aanbevolen: de eerste levert een aanzienlijke prestatiehit op wanneer de strijd hoog is, en de laatste creëert veel objecten, waardoor de garbage collection onder druk komt te staan.

Het is de moeite waard om te vermelden dat, sinds Java 8, een nieuw DateTimeFormatter klasse is geïntroduceerd. De nieuwe DateTimeFormatter klasse is onveranderlijk en draadveilig. Als we met Java 8 of hoger werken, gebruiken we het nieuwe DateTimeFormatter klasse wordt aanbevolen.

3. Data ontleden

SimpleDateFormat en Datumnotatie we kunnen niet alleen datums opmaken, maar we kunnen de bewerking ook ongedaan maken. De ... gebruiken ontleden methode, kunnen we voer het Draad weergave van een datum en retourneer de Datum object equivalent:

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

Het is belangrijk op te merken dat de patroon geleverd in de constructor moet dezelfde indeling hebben als de geparseerde datum de ... gebruiken ontleden methode.

4. Datum-tijdpatronen

SimpleDateFormat biedt een breed scala aan verschillende opties bij het formatteren van datums. Hoewel de volledige lijst beschikbaar is in JavaDocs, gaan we enkele van de meer algemeen gebruikte opties bekijken:

BriefDatum ComponentVoorbeeld
M.Maand12; Dec
yjaar94
ddag23; Ma
H.uur03
mminuut57

De uitvoer die door de datumcomponent wordt geretourneerd, hangt ook sterk af van het aantal gebruikte tekens binnen de Draad. Laten we bijvoorbeeld de maand juni nemen. Als we de datumreeks definiëren als:

"MM"

Dan verschijnt ons resultaat als de cijfercode - 06. Als we echter nog een M aan onze datumreeks toevoegen:

"MMM"

Dan verschijnt onze resulterende opgemaakte datum als het woord Jun.

5. Landinstellingen toepassen

De SimpleDateFormat klasse ook ondersteunt een breed scala aan landinstellingen die wordt ingesteld wanneer de constructor wordt aangeroepen.

Laten we dit in praktijk brengen door een datum in het Frans op te maken. We instantiëren een SimpleDateFormat object tijdens het leveren Lokaal.FRANS aan de constructeur.

SimpleDateFormat franceDateFormatter = nieuwe SimpleDateFormat ("EEEEE dd-MMMMMMM-jjjj", Locale.FRANCE); Datum myWed Wednesday = nieuwe datum (1539341312904L); assertTrue (franceDateFormatter.format (myWed Wednesday) .startsWith ("vendredi"));

Door een bepaalde datum op te geven, een woensdagmiddag, kunnen we stellen dat onze franceDateFormatter heeft de datum correct opgemaakt. De nieuwe datum begint correct met Vendredi -Frans voor woensdag!

Het is de moeite waard om een ​​klein beetje op te merken in de locale-versie van de constructor - hoewel veel landinstellingen worden ondersteund, is volledige dekking niet gegarandeerd. Oracle raadt aan om de fabrieksmethoden te gebruiken op Datumnotatie klasse om lokale dekking te garanderen.

6. Tijdzones wijzigen

Sinds SimpleDateFormat breidt de Datumnotatie klasse, kunnen we ook manipuleer de tijdzone met behulp van de setTimeZone methode. Laten we dit eens in actie bekijken:

Datum nu = nieuwe datum (); SimpleDateFormat simpleDateFormat = nieuwe SimpleDateFormat ("EEEE dd-MMM-jj HH: mm: ssZ"); simpleDateFormat.setTimeZone (TimeZone.getTimeZone ("Europa / Londen")); logger.info (simpleDateFormat.format (nu)); simpleDateFormat.setTimeZone (TimeZone.getTimeZone ("America / New_York")); logger.info (simpleDateFormat.format (nu));

In bovenstaand voorbeeld leveren wij hetzelfde Datum naar twee verschillende tijdzones op hetzelfde SimpleDateFormat voorwerp. We hebben ook het ‘Z'-teken tot het einde van het patroon Draad om de tijdzoneverschillen aan te geven. De output van de formaat methode wordt vervolgens gelogd voor de gebruiker.

Als we rennen, kunnen we de huidige tijden zien ten opzichte van de twee tijdzones:

INFO: vrijdag 12-okt-18 12: 46: 14 + 0100 INFO: vrijdag 12-okt-18 07: 46: 14-0400

7. Samenvatting

In deze tutorial hebben we een diepe duik genomen in de fijne kneepjes van SimpleDateFormat.

We hebben gekeken hoe instantiëren SimpleDateFormat evenals hoe de patroon Draad heeft invloed op hoe de datum wordt opgemaakt.

We speelden met het wijzigen van de landinstellingen van de outputstring voordat je er eindelijk mee experimenteert tijdzones gebruiken.

Zoals altijd is de volledige broncode te vinden op GitHub.