Introduksjon til Java 8 Date / Time API

1. Oversikt

Java 8 introduserte nye APIer for Dato og Tid for å løse manglene til de eldre java.util.Date og java.util.Kalender.

Som en del av denne artikkelen, la oss starte med problemene i den eksisterende Dato og Kalender API-er, og la oss diskutere hvordan den nye Java 8 Dato og Tid APIer adresserer dem.

Vi vil også se på noen av kjerneklassene i det nye Java 8-prosjektet som er en del av java.time pakke som LocalDate, LocalTime, LocalDateTime, ZonedDateTime, periode, varighet og deres støttede API-er.

2. Problemer med det eksisterende Dato/Tid APIer

  • Trådsikkerhet - Den Dato og Kalender klasser er ikke trådsikre, slik at utviklere kan håndtere hodepine ved problemer med å feilsøke samtidighet og å skrive tilleggskode for å håndtere trådsikkerhet. Tvert imot det nye Dato og Tid API-er introdusert i Java 8 er uforanderlige og trådsikre, og tar dermed den samtidige hodepinen fra utviklere.
  • API-er Design og enkel forståelse - Den Dato og Kalender API-er er dårlig designet med utilstrekkelige metoder for å utføre daglige operasjoner. Den nye Dato tid API-er er ISO-sentriske og følger konsistente domenemodeller for dato, tid, varighet og perioder. Det finnes et bredt utvalg av verktøy som støtter de vanligste operasjonene.
  • Zonedate og Tid - Utviklere måtte skrive tilleggslogikk for å håndtere tidssonelogikk med de gamle API-ene, mens med de nye API-ene kan håndtering av tidssone gjøres med Lokalt og Zonedate/Tid APIer.

3. Bruke LocalDate, Lokal tid og LocalDateTime

De mest brukte klassene er LocalDate, Lokal tid og LocalDateTime. Som navnene indikerer representerer de den lokale datoen / tiden fra observatørens kontekst.

Disse klassene brukes hovedsakelig når tidssone ikke er spesifikt spesifisert i konteksten. Som en del av denne delen vil vi dekke de mest brukte API-ene.

3.1. Jobber med LocalDate

De LocalDate representerer en dato i ISO-format (åååå-MM-dd) uten tid.

Den kan brukes til å lagre datoer som bursdager og lønningsdager.

En forekomst av gjeldende dato kan opprettes fra systemklokken som nedenfor:

LocalDate localDate = LocalDate.now ();

De LocalDate som representerer en bestemt dag, måned og år, kan du få tak i “av”-Metoden eller ved å bruke“analysere”-Metoden. For eksempel representerer kodebitene nedenfor LocalDate for 20. februar 2015:

LocalDate.of (2015, 02, 20); LocalDate.parse ("2015-02-20");

De LocalDate gir forskjellige verktøy for å skaffe en rekke informasjon. La oss ta en titt på noen av disse API-metodene.

Følgende kodebit får den gjeldende lokale datoen og legger til en dag:

LocalDate i morgen = LocalDate.now (). PlusDays (1);

Dette eksemplet får dagens dato og trekker en måned. Legg merke til hvordan den godtar en enum som tidsenhet:

LocalDate previousMonthSameDay = LocalDate.now (). Minus (1, ChronoUnit.MONTHS);

I de følgende to kodeeksemplene analyserer vi datoen “2016-06-12” og får henholdsvis ukedag og månedsdag. Legg merke til returverdiene, den første er et objekt som representerer Ukedag mens den andre i en int som representerer månedens ordinære verdi:

DayOfWeek søndag = LocalDate.parse ("2016-06-12"). GetDayOfWeek (); int tolv = LocalDate.parse ("2016-06-12"). getDayOfMonth ();

Vi kan teste om en dato oppstår i et skuddår. I dette eksemplet tester vi om dagens dato inntreffer er et skuddår:

boolsk leapYear = LocalDate.now (). isLeapYear ();

Forholdet mellom en dato og en annen kan bestemmes å skje før eller etter en annen dato:

boolsk notBefore = LocalDate.parse ("2016-06-12") .isBefore (LocalDate.parse ("2016-06-11")); boolsk isAfter = LocalDate.parse ("2016-06-12") .isAfter (LocalDate.parse ("2016-06-11"));

Dato grenser kan fås fra en gitt dato. I de følgende to eksemplene får vi LocalDateTime som representerer begynnelsen på dagen (2016-06-12T00: 00) for den gitte datoen og LocalDate som representerer henholdsvis begynnelsen av måneden (2016-06-01):

LocalDateTime beginningOfDay = LocalDate.parse ("2016-06-12"). AtStartOfDay (); LocalDate firstDayOfMonth = LocalDate.parse ("2016-06-12"). Med (TemporalAdjusters.firstDayOfMonth ());

La oss nå se på hvordan vi jobber med lokal tid.

3.2. Jobber med Lokal tid

De Lokal tid representerer tid uten dato.

Lik LocalDate en forekomst av Lokal tid kan opprettes fra systemklokken eller ved bruk av "parse" og "of" -metoden. Se raskt på noen av de mest brukte API-ene nedenfor.

En forekomst av gjeldende Lokal tid kan opprettes fra systemklokken som nedenfor:

LocalTime nå = LocalTime.now ();

I nedenstående kodeeksempel, vi lager en Lokal tid som representerer 06:30 ved å analysere en strengrepresentasjon:

LocalTime sixThirty = LocalTime.parse ("06:30");

Fabriksmetoden “av” kan brukes til å lage en Lokal tid. For eksempel oppretter koden nedenfor Lokal tid som representerer 06:30 ved bruk av fabrikkmetoden:

LocalTime sixThirty = LocalTime.of (6, 30);

Eksemplet nedenfor skaper en Lokal tid ved å analysere en streng og legger til en time til den ved hjelp av "pluss" API. Resultatet ville bli Lokal tid som representerer 07:30:

LocalTime sevenThirty = LocalTime.parse ("06:30"). Pluss (1, ChronoUnit.HOURS);

Ulike getter-metoder er tilgjengelige som kan brukes til å få bestemte tidsenheter som time, min og sekunder som nedenfor:

int seks = LocalTime.parse ("06:30"). getHour ();

Vi kan også sjekke om en bestemt tid er før eller etter en annen spesifikk tid. Kodeprøven nedenfor sammenligner to Lokal tid som resultatet ville være sant for:

boolsk isbefore = LocalTime.parse ("06:30"). isBefore (LocalTime.parse ("07:30"));

Maks, min og middagstid på en dag kan fås med konstanter i Lokal tid klasse. Dette er veldig nyttig når du utfører databasespørsmål for å finne poster innen et gitt tidsrom. For eksempel representerer koden nedenfor 23: 59: 59.99:

LocalTime maxTime = LocalTime.MAX

La oss nå dykke inn i LocalDateTime.

3.3. Jobber med LocalDateTime

De LocalDateTime brukes til å representere en kombinasjon av dato og klokkeslett.

Dette er den mest brukte klassen når vi trenger en kombinasjon av dato og tid. Klassen tilbyr en rekke APIer, og vi vil se på noen av de mest brukte.

En forekomst av LocalDateTime kan fås fra systemklokken som ligner på LocalDate og Lokal tid:

LocalDateTime.now ();

Kodeprøvene nedenfor forklarer hvordan du oppretter en forekomst ved bruk av "of" og "parse" -metodene fra fabrikken. Resultatet ville være et LocalDateTime forekomst som representerer 20. februar 2015, 06:30:

LocalDateTime.of (2015, måned. FEBRUAR, 20, 06, 30);
LocalDateTime.parse ("2015-02-20T06: 30: 00");

Det finnes verktøy-API-er som støtter tillegg og subtraksjon av bestemte tidsenheter som dager, måneder, år og minutter er tilgjengelige. Kodeeksemplene nedenfor viser bruken av "pluss" og "minus" -metoder. Disse API-ene oppfører seg akkurat som kolleger i LocalDate og Lokal tid:

localDateTime.plusDays (1);
localDateTime.minusHours (2);

Getter-metoder er tilgjengelige for å trekke ut spesifikke enheter som ligner på dato- og tidsklassene. Gitt ovennevnte forekomst av LocalDateTimevil kodeeksemplet nedenfor returnere februar måned:

localDateTime.getMonth ();

4. Bruke ZonedDateTime API

Java 8 gir ZonedDateTime når vi trenger å håndtere tidssone spesifikk dato og tid. De ZoneId er en identifikator som brukes til å representere forskjellige soner. Det er omtrent 40 forskjellige tidssoner og ZoneId brukes til å representere dem som følger.

I denne kodebiten lager vi en sone for Paris:

ZoneId zoneId = ZoneId.of ("Europe / Paris"); 

Et sett med alle sone-ID-er kan fås som nedenfor:

Sett allZoneIds = ZoneId.getAvailableZoneIds ();

De LocalDateTime kan konverteres til en bestemt sone:

ZonedDateTime zonedDateTime = ZonedDateTime.of (localDateTime, zoneId);

De ZonedDateTime gir analysere metode for å få tidsspesifikk dato:

ZonedDateTime.parse ("2015-05-03T10: 15: 30 + 01: 00 [Europe / Paris]");

En annen måte å jobbe med tidssone på er å bruke OffsetDateTime. De OffsetDateTime er en uforanderlig fremstilling av en dato-tid med en motregning. Denne klassen lagrer alle dato- og tidsfelter med en presisjon på nanosekunder, samt forskyvning fra UTC / Greenwich.

De OffSetDateTime forekomst kan opprettes som nedenfor ved hjelp av ZoneOffset. Her lager vi en LocalDateTime som representerer 06:30 20. februar 2015:

LocalDateTime localDateTime = LocalDateTime.of (2015, måned. FEBRUAR, 20, 06, 30);

Deretter legger vi to timer til tiden ved å lage en ZoneOffset og innstilling for localDateTime forekomst:

ZoneOffset offset = ZoneOffset.of ("+ 02:00"); OffsetDateTime offSetByTwo = OffsetDateTime .of (localDateTime, offset);

Vi har nå en localDateTime av 2015-02-20 06:30 +02: 00. La oss nå gå videre til hvordan du endrer dato og klokkeslett ved å bruke Periode og Varighet klasser.

5. Bruke Periode og Varighet

De Periode klasse representerer en mengde tid når det gjelder år, måneder og dager og Varighet klasse representerer en mengde tid i form av sekunder og nano sekunder.

5.1. Jobber med Periode

De Periode klasse er mye brukt til å endre verdier for en dato eller for å oppnå forskjellen mellom to datoer:

LocalDate initialDate = LocalDate.parse ("10.05.2007");

De Dato kan manipuleres ved hjelp av Periode som vist i følgende kodebit:

LocalDate finalDate = initialDate.plus (Period.ofDays (5));

De Periode klassen har forskjellige getter-metoder som getYears, getMonths og getDays for å få verdier fra en Periode gjenstand. Kodeeksemplet nedenfor returnerer en int verdien av 5 når vi prøver å få forskjell når det gjelder dager:

int five = Period.between (initialDate, finalDate) .getDays ();

De Periode mellom to datoer kan fås i en bestemt enhet, for eksempel dager eller måned eller år, ved hjelp av ChronoUnit.between:

lang fem = ChronoUnit.DAYS.between (initialDate, finalDate);

Dette kodeeksemplet returnerer fem dager. La oss fortsette med å ta en titt på Varighet klasse.

5.2. Jobber med Varighet

Lik Periode, de Varighetsklasse er bruk for å håndtere Tid. I den følgende koden lager vi en Lokal tid 6:30 og legg deretter til en varighet på 30 sekunder for å lage en Lokal tid 06:30:30:

LocalTime initialTime = LocalTime.of (6, 30, 0); LocalTime finalTime = initialTime.plus (Duration.ofSeconds (30));

De Varighet mellom to øyeblikk kan fås enten som en Varighet eller som en bestemt enhet. I den første kodebiten bruker vi mellom() metoden for Varighet klasse for å finne tidsforskjellen mellom finalTime og initialTime og returner differansen i sekunder:

lang tretti = Duration.between (initialTime, finalTime) .getSeconds ();

I det andre eksemplet bruker vi mellom() metoden for ChronoUnit klasse for å utføre den samme operasjonen:

lang tretti = ChronoUnit.SECONDS.between (initialTime, finalTime);

Nå skal vi se på hvordan du konverterer eksisterende Dato og Kalender til nytt Dato/Tid.

6. Kompatibilitet med Dato og Kalender

Java 8 har lagt til toInstant () metode som hjelper til med å konvertere eksisterende Dato og Kalender forekomst til nytt Date Time API som i følgende kodebit:

LocalDateTime.ofInstant (date.toInstant (), ZoneId.systemDefault ()); LocalDateTime.ofInstant (calendar.toInstant (), ZoneId.systemDefault ());

De LocalDateTime kan konstrueres fra epoke sekunder som nedenfor. Resultatet av koden nedenfor vil være et LocalDateTime representerer 2016-06-13T11: 34: 50:

LocalDateTime.ofEpochSecond (1465817690, 0, ZoneOffset.UTC);

La oss nå gå videre til Dato og Tid formatering.

7. Dato og Tid Formatering

Java 8 gir APIer for enkel formatering av Dato og Tid:

LocalDateTime localDateTime = LocalDateTime.of (2015, måned. JANUAR, 25, 6, 30);

Koden nedenfor overfører et ISO-datoformat for å formatere den lokale datoen. Resultatet vil være 2015-01-25:

String localDateString = localDateTime.format (DateTimeFormatter.ISO_DATE);

De DateTimeFormatter gir forskjellige standardformateringsalternativer. Egendefinerte mønstre kan også leveres for å formatere metoden, som nedenfor, som vil returnere a LocalDate som 2015/01/25:

localDateTime.format (DateTimeFormatter.ofPattern ("åååå / MM / dd"));

Vi kan passere i formateringsstil enten som KORT, LANG eller MEDIUM som en del av formateringsalternativet. Kodeprøven nedenfor vil gi et resultat som representerer LocalDateTime i 25. januar 2015, 06:30:00:

localDateTime .format (DateTimeFormatter.ofLocalizedDateTime (FormatStyle.MEDIUM)) .withLocale (Locale.UK);

La oss ta en titt på alternativer som er tilgjengelige for Java 8 Core Dato/Tid APIer.

8. Backport og alternative alternativer

8.1. Bruke Project Threeten

For organisasjoner som er på vei til å flytte til Java 8 fra Java 7 eller Java 6 og ønsker å bruke dato og klokkeslett-API, gir prosjekt tretten backport-muligheten. Utviklere kan bruke klasser som er tilgjengelige i dette prosjektet for å oppnå samme funksjonalitet som den nye Java 8 Dato og Tid API og når de flytter til Java 8, kan pakkene byttes. Artefakt for prosjektet tretten finner du i Maven Central Repository:

 org.threeten threetenbp 1.3.1 

8.2. Joda-Time Library

Et annet alternativ for Java 8 Dato og Tid biblioteket er Joda-Time-biblioteket. Faktisk Java 8 Dato tid API-er har blitt ledet i fellesskap av forfatteren av Joda-Time-biblioteket (Stephen Colebourne) og Oracle. Dette biblioteket gir stort sett alle funksjoner som støttes i Java 8 Dato tid prosjekt. Artefakten kan bli funnet i maven sentral ved å inkludere nedenstående pom-avhengighet i prosjektet ditt:

 joda-tid joda-tid 2.9.4 

9. Konklusjon

Java 8 tilbyr et rikt sett med APIer med konsistent API-design for enklere utvikling.

Kodeeksemplene for artikkelen ovenfor finner du i Java 8 Date / Time git repository.