Introduktion til Joda-Time

1. Introduktion

Joda-Time er det mest anvendte dato- og tidsbehandlingsbibliotek inden frigivelsen af ​​Java 8. Formålet var at tilbyde en intuitiv API til behandling af dato og klokkeslæt og også løse de designproblemer, der eksisterede i Java Date / Time API.

De centrale koncepter implementeret i dette bibliotek blev introduceret i JDK-kernen med frigivelsen af ​​Java 8-versionen. Den nye API for dato og klokkeslæt findes i java.tid pakke (JSR-310). En oversigt over disse funktioner kan findes i denne artikel.

Efter udgivelsen af ​​Java 8 betragter forfattere projektet for at være for det meste færdigt og rådes til at bruge Java 8 API, hvis det er muligt.

2. Hvorfor bruge Joda-Time?

Datoen / klokkeslættet API, før Java 8, præsenterede flere designproblemer.

Blandt problemerne er det faktum, at Dato og SimpleDateFormatter klasser er ikke trådsikre. For at løse dette problem, Joda-Time bruger uforanderlige klasser til håndtering af dato og klokkeslæt.

Det Dato klasse repræsenterer ikke en faktisk dato, men i stedet angiver den et øjeblik i tid med millisekundpræcision. Året i en Dato starter fra 1900, mens de fleste af datoperationerne normalt bruger Epoch-tid, der starter fra 1. januar 1970.

Også offset for dag, måned og år Dato er modstridende. Dage starter ved 0, mens måned begynder fra 1. For at få adgang til nogen af ​​dem skal vi bruge Kalender klasse. Joda-Time tilbyder et rent og flydende API til håndtering af datoer og klokkeslæt.

Joda-Time tilbyder også support til otte kalendersystemer, mens Java kun tilbyder 2: gregoriansk - java.util.GregorianCalendar og japansk - java.util.JapaneseImperialCalendar.

3. Opsætning

For at inkludere funktionaliteten i Joda-Time-biblioteket skal vi tilføje følgende afhængighed fra Maven Central:

 joda-tid joda-tid 2.10 

4. Biblioteksoversigt

Joda-Time modellerer begrebet dato og tid ved hjælp af klasser i org.joda.time pakke.

Blandt disse klasser er de mest anvendte:

  • LocalDate - repræsenterer en dato uden tid
  • Lokal tid - repræsenterer tiden uden tidszonen
  • LocalDateTime - repræsenterer både dato og klokkeslæt uden en tidszone
  • Øjeblikkelig - repræsenterer et nøjagtigt tidspunkt i millisekunder fra Java-epoken fra 1970-01-01T00: 00: 00Z
  • Varighed - repræsenterer varigheden i millisekunder mellem 2 tidspunkter
  • Periode - svarende til Varighed, men giver adgang til individuelle komponenter i dato- og tidsobjektet, som år, måned, dage osv.
  • Interval - repræsenterer tidsintervallet mellem to øjeblikke

Andre vigtige funktioner er dato parsere og formatere. Disse kan findes i org.joda.time.format pakke.

Det kalendersystem og tidszone specifikke klasser kan findes i org.joda.time.chrono og org.joda.time.tz pakker.

Lad os se på nogle eksempler, hvor vi bruger de vigtigste funktioner i Joda-Time til at håndtere dato og tid.

5. Repræsenterer dato og klokkeslæt

5.1. Aktuel dato og tid

Den aktuelle dato uden tidsinformation kan opnås ved hjælp af nu() metode fra det LocalDate klasse:

LocalDate currentDate = LocalDate.now ();

Når vi kun har brug for det aktuelle tidspunkt uden datooplysninger, kan vi bruge Lokal tid klasse:

LocalTime currentTime = LocalTime.now ();

For at få en repræsentation af den aktuelle dato og tid uden at overveje tidszonen, vi kan bruge LocalDateTime:

LocalDateTime currentDateAndTime = LocalDateTime.now ();

Brug nu currentDateAndTime, kan vi konvertere det til de andre typer objekter, der modellerer dato og klokkeslæt.

Vi kan få en Dato tid objekt (som tager højde for tidszonen) ved hjælp af metoden toDateTime (). Når tid ikke er nødvendig, kan vi konvertere den til en LocalDate med metoden toLocalDate (), og når vi kun har brug for den tid, vi kan bruge toLocalTime () at få en Lokal tid objekt:

DateTime dateTime = currentDateAndTime.toDateTime (); LocalDate localDate = currentDateAndTime.toLocalDate (); LocalTime localTime = currentDateAndTime.toLocalTime ();

Alle ovenstående metoder har en overbelastet metode, der accepterer en DateTimeZone objekt for at hjælpe os med at repræsentere datoen eller klokkeslættet i den angivne tidszone:

LocalDate currentDate = LocalDate.now (DateTimeZone.forID ("America / Chicago"));

Joda-Time tilbyder også fremragende integration med Java Date and Time API. Konstruktørerne accepterer en java.util.Date objekt og også, vi kan bruge til dato() metode til at returnere en java.util.Date objekt:

LocalDateTime currentDateTimeFromJavaDate = ny LocalDateTime (ny dato ()); Dato currentJavaDate = currentDateTimeFromJavaDate.toDate ();

5.2. Brugerdefineret dato og klokkeslæt

For at repræsentere brugerdefineret dato og klokkeslæt giver Joda-Time os flere konstruktører. Vi kan specificere følgende objekter:

  • en Øjeblikkelig
  • en Java Dato objekt
  • -en Snor repræsentation af dato og klokkeslæt ved hjælp af ISO-format
  • dele af dato og klokkeslæt: år, måned, dag, time, minut, sekund, millisekund
Dato oneMinuteAgoDate = ny dato (System.currentTimeMillis () - (60 * 1000)); Øjeblikkelig oneMinutesAgoInstant = ny øjeblikkelig (oneMinuteAgoDate); DateTime customDateTimeFromInstant = ny DateTime (oneMinutesAgoInstant); DateTime customDateTimeFromJavaDate = ny DateTime (oneMinuteAgoDate); DateTime customDateTimeFromString = ny DateTime ("2018-05-05T10: 11: 12.123"); DateTime customDateTimeFromParts = ny DateTime (2018, 5, 5, 10, 11, 12, 123); 

En anden måde, hvorpå vi kan definere en brugerdefineret dato og et klokkeslæt, er ved at analysere en given Snor repræsentation af en dato og et klokkeslæt i ISO-format:

DateTime parsedDateTime = DateTime.parse ("2018-05-05T10: 11: 12.123");

Vi kan også analysere brugerdefinerede repræsentationer af en dato og et klokkeslæt ved at definere en brugerdefineret DateTimeFormatter:

DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern ("MM / dd / åååå HH: mm: ss"); DateTime parsedDateTimeUsingFormatter = DateTime.parse ("05/05/2018 10:11:12", dateTimeFormatter);

6. Arbejde med dato og klokkeslæt

6.1. Ved brug af Øjeblikkelig

En Øjeblikkelig repræsenterer antallet af millisekunder fra 1970-01-01T00: 00: 00Z indtil et givet tidspunkt. For eksempel kan det aktuelle øjeblik i tid opnås ved hjælp af standardkonstruktøren eller metoden nu():

Øjeblikkelig øjeblikkelig = ny øjeblikkelig (); Øjeblikkelig. Nu ();

At oprette en Øjeblikkelig i et tilpasset øjeblik kan vi bruge en af ​​konstruktørerne eller bruge metoderne afEpochMilli () og ofEpochSecond ():

Øjeblikkelig instantFromEpochMilli = Instant.ofEpochMilli (milliesFromEpochTime); Øjeblikkelig instantFromEpocSeconds = Instant.ofEpochSecond (secondsFromEpochTime);

Konstruktørerne accepterer en Snor repræsenterer en dato og et klokkeslæt i ISO-format, en Java Dato eller a lang værdi, der repræsenterer antallet af millisekunder fra 1970-01-01T00: 00: 00Z:

Øjeblikkelig instantFromString = ny Øjeblikkelig ("2018-05-05T10: 11: 12"); Øjeblikkelig instantFromDate = ny øjeblikkelig (oneMinuteAgoDate); Øjeblikkelig instantFromTimestamp = ny Øjeblikkelig (System.currentTimeMillis () - (60 * 1000));

Når dato og klokkeslæt er repræsenteret som en Snor vi har mulighed for at analysere Snor ved hjælp af vores ønskede format:

Øjeblikkelig parsedInstant = Øjeblikkelig.parse ("05/05/2018 10:11:12", dateTimeFormatter);

Nu hvor vi ved hvad Øjeblikkelig repræsenterer, og hvordan vi kan oprette en, lad os se, hvordan den kan bruges.

At sammenligne med Øjeblikkelig objekter, vi kan bruge sammenligne med() fordi det implementerer Sammenlignelig interface, men også vi kan bruge de Joda-Time API-metoder, der findes i Læsbar Øjeblikkelig interface, som Øjeblikkelig implementerer også:

assertTrue (instantNow.compareTo (oneMinuteAgoInstant)> 0); assertTrue (instantNow.isAfter (oneMinuteAgoInstant)); assertTrue (oneMinuteAgoInstant.isBefore (instantNow)); assertTrue (oneMinuteAgoInstant.isBeforeNow ()); assertFalse (oneMinuteAgoInstant.isEqual (instantNow));

En anden nyttig funktion er det Øjeblikkelig kan konverteres til en Dato tid objekt eller begivenhed en Java Dato:

DateTime dateTimeFromInstant = instant.toDateTime (); Dato javaDateFromInstant = instant.toDate ();

Når vi har brug for at få adgang til dele af en dato og et klokkeslæt, som året, timen osv., Kan vi bruge få() metode og angiv en DateTimeField:

int år = instant.get (DateTimeFieldType.year ()); int måned = instant.get (DateTimeFieldType.monthOfYear ()); int dag = instant.get (DateTimeFieldType.dayOfMonth ()); int time = instant.get (DateTimeFieldType.hourOfDay ());

Nu hvor vi dækkede Øjeblikkelig klasse lad os se nogle eksempler på, hvordan vi kan bruge Varighed, Periode og Interval.

6.2. Ved brug af Varighed, Periode og Interval

EN Varighed repræsenterer tiden i millisekunder mellem to tidspunkter, eller i dette tilfælde kan det være to Øjeblikkelige. Vi bruger dette, når vi har brug for at tilføje eller trække en bestemt tid til eller fra en anden Øjeblikkelig uden at overveje kronologi og tidszoner:

long currentTimestamp = System.currentTimeMillis (); lang oneHourAgo = nuværende tidsstempel - 24 * 60 * 1000; Varighed varighed = ny varighed (oneHourAgo, nuværende tidsstempel); Instant.now () plus (varighed);

Vi kan også bestemme, hvor mange dage, timer, minutter, sekunder eller millisekunder varigheden repræsenterer:

long durationInDays = duration.getStandardDays (); long durationInHours = duration.getStandardHours (); long durationInMinutes = duration.getStandardMinutes (); long durationInSeconds = duration.getStandardSeconds (); lang varighedInMilli = varighed.getMillis ();

Den største forskel mellem Periode og Varighed er det Periode er defineret i form af dets dato- og tidskomponenter (år, måneder, timer osv.) og repræsenterer ikke et nøjagtigt antal millisekunder. Ved brug Periode beregninger af dato og tid vil overveje tidszone og sommertid.

For eksempel tilføje en Periode fra 1 måned til 1. februar vil resultere i datorepræsentation af 1. marts. Ved hjælp af Periode biblioteket vil tage højde for skudår.

Hvis vi skal bruge en Varighed vi resultatet ville ikke være korrekt, fordi Varighed repræsenterer en fast tid, der ikke tager højde for kronologi eller tidszoner:

Periode periode = ny periode (). Med måneder (1); LocalDateTime datePlusPeriod = localDateTime.plus (periode);

En Interval, som navnet angiver, repræsenterer datoen og tidsintervallet mellem to faste tidspunkter repræsenteret af to Øjeblikkelig genstande:

Intervalinterval = nyt interval (oneMinuteAgoInstant, instantNow);

Klassen er nyttig, når vi skal kontrollere, om to intervaller overlapper hinanden eller beregner afstanden mellem dem. Det overlapning () metoden returnerer den overlappende Interval eller nul når de ikke overlapper hinanden:

Øjeblikkelig startInterval1 = ny øjeblikkelig ("2018-05-05T09: 00: 00.000"); Øjeblikkelig endInterval1 = ny Øjeblikkelig ("2018-05-05T11: 00: 00.000"); Intervalinterval1 = nyt Interval (startInterval1, endInterval1); Øjeblikkelig startInterval2 = ny øjeblikkelig ("2018-05-05T10: 00: 00.000"); Øjeblikkelig endInterval2 = ny Øjeblikkelig ("2018-05-05T11: 00: 00.000"); Intervalinterval2 = nyt Interval (startInterval2, endInterval2); Interval overlappingInterval = interval1.overlap (interval2);

Forskellen mellem intervaller kan beregnes ved hjælp af hul () metode, og når vi vil vide, om slutningen af ​​et interval er lig med starten på et andet interval, kan vi bruge støder op () metode:

assertTrue (interval1.abuts (nyt interval (nyt øjeblikkeligt ("2018-05-05T11: 00: 00.000"), nyt øjeblikkeligt ("2018-05-05T13: 00: 00.000"))));

6.3. Dato- og tidsoperationer

Nogle af de mest almindelige operationer er at tilføje, trække fra og konvertere dato og klokkeslæt. Biblioteket giver specifikke metoder til hver af klasser LocalDate, Lokal tid, LocalDateTimeog Dato tid. Det er vigtigt at bemærke, at disse klasser er uforanderlige, så hver metodeopkald vil skabe et nyt objekt af sin type.

Lad os tage LocalDateTime for øjeblikket og prøv at ændre dens værdi:

LocalDateTime currentLocalDateTime = LocalDateTime.now ();

For at tilføje en ekstra dag til currentLocalDateTime vi bruger plusDays () metode:

LocalDateTime nextDayDateTime = currentLocalDateTime.plusDays (1);

Vi kan også bruge plus() metode til at tilføje en Periode eller Varighed til vores currentLocalDateTime:

Periode oneMonth = ny periode () medMonths (1); LocalDateTime nextMonthDateTime = currentLocalDateTime.plus (oneMonth);

Metoderne er ens for de andre dato- og tidskomponenter, for eksempel plusÅr () for at tilføje ekstra år, plusSeconds () for at tilføje flere sekunder og så videre.

At trække en dag fra vores currentLocalDateTime vi kan bruge minusDage () metode:

LocalDateTime previousDayLocalDateTime = currentLocalDateTime.minusDays (1);

Derudover gør vi beregninger med dato og tid, vi kan også indstille individuelle dele af datoen eller klokkeslættet. For eksempel kan indstilling af timen til 10 opnås ved hjælp af withHourOfDay () metode. Andre metoder, der starter med præfikset "med" kan bruges til at indstille komponenter til den dato eller det tidspunkt:

LocalDateTime currentDateAtHour10 = currentLocalDateTime .withHourOfDay (0) .withMinuteOfHour (0) .withSecondOfMinute (0) .withMillisOfSecond (0);

Et andet vigtigt aspekt er, at vi kan konvertere fra en dato og tidsklasse til en anden. For at gøre dette kan vi bruge specifikke metoder leveret af biblioteket:

  • toDateTime () - konverterer LocalDateTime til en Dato tid objekt
  • toLocalDate () - konverterer LocalDateTime til en LocalDate objekt
  • toLocalTime () - konverterer LocalDateTime til et LocalTime-objekt
  • til dato() - konverterer LocalDateTime til en Java Dato objekt

7. Arbejde med tidszoner

Joda-Time gør det let for os at arbejde med forskellige tidszoner og skifte mellem dem. Vi har DateTimeZone abstrakt klasse, der bruges til at repræsentere alle aspekter vedrørende en tidszone.

Den standard tidszone, der bruges af Joda-Time, er valgt fra user.timezone Java-systemegenskab. Bibliotekets API giver os mulighed for at specificere individuelt for hver klasse eller beregning, hvilken tidszone der skal bruges. For eksempel kan vi oprette et LocalDateTime-objekt

Når vi ved, at vi bruger en bestemt tidszone på tværs af hele applikationen, kan vi indstille standardtidszonen:

DateTimeZone.setDefault (DateTimeZone.UTC);

Fra nu af vises alle dato- og tidshandlinger, hvis ikke andet er angivet, i UTC-tidszonen.

For at se alle de tilgængelige tidszoner kan vi bruge metoden getAvailableIDs ():

DateTimeZone.getAvailableIDs ()

Når vi skal repræsentere datoen eller klokkeslættet i en bestemt tidszone, kan vi bruge en hvilken som helst klasse Lokal tid, LocalDate, LocalDateTime, Dato tid og specificer i konstruktøren DateTimeZone objekt:

DateTime dateTimeInChicago = ny DateTime (DateTimeZone.forID ("America / Chicago")); DateTime dateTimeInBucharest = ny DateTime (DateTimeZone.forID ("Europa / Bukarest")); LocalDateTime localDateTimeInChicago = ny LocalDateTime (DateTimeZone.forID ("America / Chicago"));

Også når vi konverterer mellem disse klasser, kan vi specificere den ønskede tidszone. Metoden toDateTime () accepterer en DateTimeZone objekt og til dato() accepterer java.util.TimeZone-objekt:

DateTime convertDateTime = localDateTimeInChicago.toDateTime (DateTimeZone.forID ("Europe / Bucharest")); Dato konverteret dato = localDateTimeInChicago.toDate (TimeZone.getTimeZone ("Europa / Bukarest"));

8. Konklusion

Joda-Time er et fantastisk bibliotek, der startede med det primære mål at løse problemerne i JDK med hensyn til dato og klokkeslæt. Det blev snart den de facto bibliotek til håndtering af dato og tid og for nylig blev hovedkoncepterne fra det introduceret i Java 8.

Det er vigtigt at bemærke, at forfatteren overvejer det “At være et stort set færdigt projekt” og anbefaler at migrere den eksisterende kode for at bruge implementeringen af ​​Java 8.

Kildekoden til artiklen er tilgængelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found