Bevezetés a Joda-Time-ba

1. Bemutatkozás

A Joda-Time a legáltalánosabban használt dátum- és időfeldolgozó könyvtár, a Java 8 kiadása előtt. Célja intuitív API-t kínált a dátum és idő feldolgozására, valamint a Java Date / Time API-ban meglévő tervezési problémákra is.

Az ebben a könyvtárban megvalósított központi fogalmak a Java 8 verzió kiadásával kerültek bevezetésre a JDK magjában. Az új dátum és idő API az java.time csomag (JSR-310). Ezen funkciók áttekintése található ebben a cikkben.

A Java 8 kiadása után a szerzők a projektet többnyire befejezettnek tartják, és javasolják a Java 8 API használatát, ha lehetséges.

2. Miért érdemes használni a Joda-Time-ot?

A Java 8 előtti dátum / idő API több tervezési problémát is felvetett.

A problémák között szerepel az a tény, hogy a Dátum és SimpleDateFormatter osztályok nem szálbiztosak. A probléma megoldása érdekében A Joda-Time változhatatlan osztályokat használ a dátum és az idő kezeléséhez.

A Dátum osztály nem egy tényleges dátumot képvisel, hanem egy pillanatnyi pillanatot határoz meg, milliszekundum pontossággal. Az év a Dátum 1900-tól kezdődik, míg a dátum műveletek többsége általában az 1970. január 1-jétől kezdődő korszakot használja.

Emellett a nap, a hónap és az év eltolódása a Dátum ellentmondásos. A napok 0-nál kezdődnek, míg a hónap 1-től kezdődik. Bármelyikük eléréséhez a Naptár osztály. A Joda-Time tiszta és folyékony API-t kínál a dátumok és az idő kezeléséhez.

A Joda-Time is kínál nyolc naptári rendszer támogatása, míg a Java csak kettőt kínál: gregorián - java.util.GregorianCalendar és japán - java.util.JapaneseImperialCalendar.

3. Beállítás

A Joda-Time könyvtár funkcionalitásának felvételéhez hozzá kell adnunk a következő függőséget a Maven Centraltól:

 joda-idő joda-idő 2.10 

4. Könyvtár áttekintése

A Joda-Time modellezi a dátum és idő fogalma osztályainak használata a org.joda.time csomag.

Ezen osztályok közül a leggyakrabban használtak:

  • LocalDate - dátumot jelöl, idő nélkül
  • Helyi idő - az időzóna nélküli időt jelöli
  • LocalDateTime - a dátumot és az időt is jelzi időzóna nélkül
  • Azonnali - egy pontos időpontot jelenít meg milliszekundumokban az 1970-01-01T00: 00: 00Z Java korszakból
  • Időtartam - az időtartamot milliszekundumban jelöli 2 időpont között
  • Időszak - hasonló Időtartam, de hozzáférést tesz lehetővé a dátum és idő objektum egyes összetevőihez, például évekhez, hónapokhoz, napokhoz stb.
  • Intervallum - a 2 pillanat közötti időintervallumot jelenti

További fontos jellemzők a dátum elemzők és formázók. Ezek megtalálhatók a org.joda.time.format csomag.

A naptárrendszer és időzóna meghatározott osztályok találhatók a org.joda.time.chrono és org.joda.time.tz csomagok.

Vessen egy pillantást néhány példára, amelyekben a Joda-Time legfontosabb jellemzőit használjuk a dátum és az idő kezelésére.

5. A dátum és az idő ábrázolása

5.1. Aktuális dátum és idő

Az aktuális dátum, időinformációk nélkül, a Most() módszer től a LocalDate osztály:

LocalDate currentDate = LocalDate.now ();

Amikor csak az aktuális időre van szükségünk, dátuminformációk nélkül, akkor használhatjuk a Helyi idő osztály:

LocalTime currentTime = LocalTime.now ();

A az aktuális dátum és idő ábrázolása anélkül, hogy figyelembe vennénk az időzónát, használhatjuk LocalDateTime:

LocalDateTime currentDateAndTime = LocalDateTime.now ();

Most, használva currentDateAndTime, konvertálhatjuk más típusú objektumokra, amelyek modellezik a dátumot és az időt.

Megszerezhetjük a Dátum idő objektum (amely figyelembe veszi az időzónát) a módszer használatával toDateTime (). Ha az idő nem szükséges, akkor a-vá alakíthatjuk át LocalDate a módszerrel toLocalDate (), és amikor csak arra az időre van szükségünk, amelyet felhasználhatunk toLocalTime () megszerezni a Helyi idő tárgy:

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

A fenti módszerek mindegyike rendelkezik túlterhelt módszerrel, amely elfogadja a DateTimeZone tárgy hogy segítsen nekünk képviselni a dátumot vagy az időt a megadott időzónában:

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

Emellett a Joda-Time kiváló integrációt kínál a Java Date and Time API-val. A kivitelezők elfogadják a java.util.Dátum objektumot és azt is használhatjuk randizni() módszer a java.util.Dátum tárgy:

LocalDateTime currentDateTimeFromJavaDate = new LocalDateTime (new Date ()); Date currentJavaDate = currentDateTimeFromJavaDate.toDate ();

5.2. Egyéni dátum és idő

Az egyedi dátum és idő ábrázolására a Joda-Time számos kivitelezőt biztosít számunkra. A következő objektumokat adhatjuk meg:

  • an Azonnali
  • egy Java Dátum tárgy
  • a Húr a dátum és az idő ábrázolása az ISO formátum használatával
  • a dátum és az idő részei: év, hónap, nap, óra, perc, másodperc, ezredmásodperc
Date oneMinuteAgoDate = új dátum (System.currentTimeMillis () - (60 * 1000)); Azonnali oneMinutesAgoInstant = új azonnali (oneMinuteAgoDate); DateTime customDateTimeFromInstant = new DateTime (oneMinutesAgoInstant); DateTime customDateTimeFromJavaDate = new DateTime (oneMinuteAgoDate); DateTime customDateTimeFromString = new DateTime ("2018-05-05T10: 11: 12.123"); DateTime customDateTimeFromParts = new DateTime (2018, 5, 5, 10, 11, 12, 123); 

Az egyéni dátum és idő meghatározásának másik módja az adott elemzés Húr dátum és idő ábrázolása ISO formátumban:

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

Szintén elemezhetjük a dátum és az idő egyedi ábrázolását egy szokás definiálásával DateTimeFormatter:

DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern ("HH / nn / éééé ÓÓ: h: mm"); DateTime parsedDateTimeUsingFormatter = DateTime.parse ("2018.05.05. 10:11:12", dateTimeFormatter);

6. Dátum és idő kezelése

6.1. Használata Azonnali

An Azonnali az ezredmásodpercek számát jelenti az 1970-01-01T00: 00: 00Z-től az adott időpillanatig. Például az aktuális időpontot az alapértelmezett konstruktor vagy a módszer segítségével lehet megszerezni Most():

Azonnali = új Azonnali (); Instant.now ();

Annak létrehozásához Azonnali egy adott pillanatban használhatjuk a kivitelezők egyikét vagy a módszereket ofEpochMilli () és ofEpochSecond ():

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

A kivitelezők elfogadják a Húr a dátumot és az időt ISO formátumban képviseli, egy Java Dátum vagy a hosszú ezredmásodpercek számát reprezentáló érték 1970-01-01T00: 00: 00Z-től:

Instant instantFromString = new Instant ("2018-05-05T10: 11: 12"); Instant instantFromDate = új azonnali (oneMinuteAgoDate); Instant instantFromTimestamp = új azonnali (System.currentTimeMillis () - (60 * 1000));

Amikor a dátum és az idő a Húr lehetőségünk van elemezni a Húr a kívánt formátum használatával:

Instant parsedInstant = Instant.parse ("2018.05.05. 10:11:12", dateTimeFormatter);

Most, hogy tudjuk, mit Azonnali képviseli és hogyan hozhatunk létre egyet, nézzük meg, hogyan lehet használni.

Összehasonlítani Azonnali tárgyakat használhatjuk összehasonlítani() mert végrehajtja a Hasonló felületen, de használhatjuk a Joda-Time API módszereket is ReadableInstant interfész, amely Azonnali megvalósítja:

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

Egy másik hasznos tulajdonság az Azonnali átalakítható a-vá Dátum idő objektum vagy esemény egy Java Dátum:

DateTime dateTimeFromInstant = instant.toDateTime (); Dátum javaDateFromInstant = instant.toDate ();

Amikor hozzáférnünk kell egy dátum és idő egyes részeihez, például évhez, órához és így tovább, használhatjuk a kap() módszert, és adja meg a DateTimeField:

int év = instant.get (DateTimeFieldType.year ()); int hónap = instant.get (DateTimeFieldType.monthOfYear ()); int nap = instant.get (DateTimeFieldType.dayOfMonth ()); int óra = instant.get (DateTimeFieldType.hourOfDay ());

Most, hogy lefedtük a Azonnali osztály lássunk néhány példát arra, hogyan használhatjuk Időtartam, Időszak és Intervallum.

6.2. Használata Időtartam, Időszak és Intervallum

A Időtartam két másodperc közötti időt milliszekundumban ábrázolja, vagy ebben az esetben kettő lehet Azonnali. Akkor fogjuk használni, amikor egy adott időtartamot hozzá kell adnunk vagy kivonnunk kell egy másikból vagy egyből Azonnali anélkül, hogy figyelembe vennék az időrendet és az időzónákat:

long currentTimestamp = System.currentTimeMillis (); hosszú oneHourAgo = currentTimestamp - 24 * 60 * 1000; Időtartam időtartama = új Időtartam (oneHourAgo, currentTimestamp); Azonnali.most (). Plusz (időtartam);

Azt is meghatározhatjuk, hogy az időtartam hány napot, órát, percet, másodpercet vagy milliszekundumot jelent:

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

A fő különbség Időszak és Időtartam az, hogy a Időszak dátum és idő komponensek (évek, hónapok, órák stb.) alapján van meghatározva, és nem jelenti pontosan a milliszekundumok számát. Használat során Időszak dátum és idő számítások figyelembe veszi az időzónát és a nyári időszámítást.

Például a Időszak 1 hónappal a február 1-jéig március 1-jei dátum szerinti képviseletet eredményez. Használva Időszak a könyvtár figyelembe veszi a szökőéveket.

Ha használni akarjuk a Időtartam mi az eredmény nem lenne helyes, mert a Időtartam rögzített időtartamot jelent, amely nem veszi figyelembe az időrendet vagy az időzónákat:

Periódus periódus = új Periódus (). A Hónapokkal (1); LocalDateTime datePlusPeriod = localDateTime.plus (időszak);

An Intervallum, amint a név is kimondja, a két rögzített időpont közötti dátumot és időintervallumot képviseli Azonnali tárgyak:

Intervallum intervallum = új intervallum (oneMinuteAgoInstant, instantNow);

Az osztály akkor hasznos, ha ellenőriznünk kell, hogy két intervallum átfedi-e egymást, vagy kiszámítani a közöttük lévő rést. A átfedés() metódus visszaadja az átfedést Intervallum vagy nulla amikor nem fedik egymást:

Azonnali indításInterval1 = új azonnali ("2018-05-05T09: 00: 00.000"); Instant endInterval1 = new Instant ("2018-05-05T11: 00: 00.000"); 1. intervallum = új intervallum (startInterval1, endInterval1); Azonnali indításInterval2 = új azonnali ("2018-05-05T10: 00: 00.000"); Instant endInterval2 = új azonnali ("2018-05-05T11: 00: 00.000"); 2. intervallum = új intervallum (startInterval2, endInterval2); Interval overlappingInterval = interval1.overlap (interval2);

Az intervallumok közötti különbség a rés() metódust, és amikor meg akarjuk tudni, hogy egy intervallum vége megegyezik-e egy másik intervallum kezdetével, használhatjuk a támaszkodik () módszer:

assertTrue (interval1.abuts (új Intervallum (új Instant ("2018-05-05T11: 00: 00.000"), új Instant ("2018-05-05T13: 00: 00.000"))));

6.3. Dátum és idő műveletek

A leggyakoribb műveletek közé tartozik a dátum és az idő összeadása, kivonása és konvertálása. A könyvtár az egyes osztályokhoz külön módszereket biztosít LocalDate, Helyi idő, LocalDateTime, és Dátum idő. Fontos megjegyezni, hogy ezek az osztályok megváltoztathatatlanok, így minden metódushívás új típusú objektumot hoz létre.

Vessünk LocalDateTime az aktuális pillanatra, és próbálja megváltoztatni az értékét:

LocalDateTime currentLocalDateTime = LocalDateTime.now ();

Egy további nap hozzáadása a következőhöz: currentLocalDateTime használjuk a plusDays () módszer:

LocalDateTime nextDayDateTime = currentLocalDateTime.plusDays (1);

Használhatjuk is plusz() módszer a Időszak vagy Időtartam a miénknek currentLocalDateTime:

Period oneMonth = új időszak (). WithMonths (1); LocalDateTime nextMonthDateTime = currentLocalDateTime.plus (oneMonth);

A módszerek hasonlóak a többi dátum és idő komponens esetében, például plusYears () plusz évek hozzáadásához, pluszSeconds () további másodpercek hozzáadásához és így tovább.

Kivonni egy napot a miénkből currentLocalDateTime használhatjuk a minusDays () módszer:

LocalDateTime előzőDayLocalDateTime = currentLocalDateTime.minusDays (1);

Ezenkívül a dátum és az idő kiszámításával beállíthatjuk a dátum vagy az idő egyes részeit is. Például az órát 10-re állíthatja a withHourOfDay () módszer. Az előtaggal kezdődő egyéb módszerek "val vel" használható az adott dátum vagy idő összetevőinek beállítására:

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

Egy másik fontos szempont, hogy konvertálhatunk dátum- és időosztály-típusból másikba. Ehhez a könyvtár által biztosított specifikus módszereket használhatjuk:

  • toDateTime () - megtért LocalDateTime a Dátum idő tárgy
  • toLocalDate () - megtért LocalDateTime a LocalDate tárgy
  • toLocalTime () - átalakítja a LocalDateTime-ot LocalTime objektummá
  • randizni() - megtért LocalDateTime Java-ra Dátum tárgy

7. Munka az időzónákkal

A Joda-Time megkönnyíti számunkra a különböző időzónákkal és azok közötti váltással való munkát. Megvan a DateTimeZone absztrakt osztály, amelyet az időzónával kapcsolatos összes szempont képviseletére használnak.

A Joda-Time által használt alapértelmezett időzóna a user.idezone Java rendszer tulajdonság. A könyvtár API lehetővé teszi, hogy osztályonként vagy számításonként külön meghatározzuk, hogy milyen időzónát kell használni. Létrehozhatunk például egy LocalDateTime objektumot

Amikor tudjuk, hogy egy adott időzónát fogunk használni az egész alkalmazásban, beállíthatjuk az alapértelmezett időzónát:

DateTimeZone.setDefault (DateTimeZone.UTC);

Ezentúl az összes dátum- és idõmûvelet, ha másként nincs meghatározva, az UTC idõzónában jelenik meg.

Az összes rendelkezésre álló időzóna megtekintéséhez használhatjuk a módszert getAvailableIDs ():

DateTimeZone.getAvailableIDs ()

Amikor a dátumot vagy az időt egy adott időzónában kell ábrázolnunk, bármelyik osztályt használhatjuk Helyi idő, LocalDate, LocalDateTime, Dátum idő és adja meg a konstruktorban a DateTimeZone tárgy:

DateTime dateTimeInChicago = new DateTime (DateTimeZone.forID ("Amerika / Chicago")); DateTime dateTimeInucharest = new DateTime (DateTimeZone.forID ("Európa / Bukarest")); LocalDateTime localDateTimeInChicago = new LocalDateTime (DateTimeZone.forID ("Amerika / Chicago"));

Ezen osztályok közötti átváltáskor megadhatjuk a kívánt időzónát is. A módszer, a metódus toDateTime () elfogadja a DateTimeZone tárgy és randizni() elfogadja a java.util.TimeZone objektumot:

DateTime convertDateTime = localDateTimeInChicago.toDateTime (DateTimeZone.forID ("Európa / Bukarest")); Date convertDate = localDateTimeInChicago.toDate (TimeZone.getTimeZone ("Európa / Bukarest"));

8. Következtetés

A Joda-Time egy fantasztikus könyvtár, amelynek fő célja a JDK dátum és idő műveletekkel kapcsolatos problémáinak kijavítása volt. Hamarosan az lett de facto könyvtárat a dátum és az idő kezelésére, a közelmúltban pedig a főbb fogalmakat a Java 8-ban vezették be.

Fontos megjegyezni, hogy a szerző úgy ítéli meg „Nagyrészt kész projektnek lenni” és javasolja a meglévő kód migrálását a Java 8 implementáció használatához.

A cikk forráskódja elérhető a GitHubon.