Úvod do Joda-Time

1. Úvod

Joda-Time je najpoužívanejšia knižnica na spracovanie dátumu a času pred vydaním Java 8. Jej účelom bolo ponúknuť intuitívne API na spracovanie dátumu a času a tiež riešiť problémy s dizajnom, ktoré existovali v rozhraní Java Date / Time API.

Ústredné koncepty implementované v tejto knižnici boli predstavené v jadre JDK vydaním verzie Java 8. Nové rozhranie API pre dátum a čas sa nachádza v java.time balíček (JSR-310). Prehľad týchto funkcií nájdete v tomto článku.

Po vydaní Java 8 autori považujú projekt za väčšinou ukončený a podľa možnosti odporúčajú používať API Java 8.

2. Prečo používať Joda-Time?

Rozhranie API pre dátum a čas, pred jazykom Java 8, predstavovalo niekoľko problémov s dizajnom.

Medzi problémy patrí skutočnosť, že Dátum a SimpleDateFormatter triedy nie sú bezpečné pre vlákna. Ak chcete vyriešiť tento problém, Joda-Time používa na spracovanie dátumu a času nemenné triedy.

The Dátum trieda nepredstavuje skutočný dátum, ale namiesto toho určuje okamih s presnosťou na milisekundy. Rok v a Dátum začína od roku 1900, zatiaľ čo väčšina operácií s dátumom zvyčajne používa epochálny čas, ktorý začína 1. januára 1970.

Taktiež započítanie dňa, mesiaca a roku a Dátum je neintuitívne. Dni začínajú od 0, zatiaľ čo mesiac začína od 1. Pre prístup k niektorému z nich musíme použiť znak Kalendár trieda. Joda-Time ponúka čisté a plynulé API na spracovanie dátumov a času.

Joda-Time tiež ponúka podpora ôsmich kalendárnych systémov, zatiaľ čo Java ponúka iba 2: gregoriánsky - java.util.GregorianCalendar a japončina - java.util.JapaneseImperialCalendar.

3. Inštalácia

Ak chcete zahrnúť funkčnosť knižnice Joda-Time, musíme pridať nasledujúcu závislosť od Maven Central:

 joda-time joda-time 2.10 

4. Prehľad knižnice

Joda-Time modeluje koncepcia dátumu a času pomocou tried v org.joda.čas balíček.

Z týchto tried sa najčastejšie používajú:

  • LocalDate - predstavuje dátum bez času
  • Miestny čas - predstavuje čas bez časového pásma
  • LocalDateTime - predstavuje dátum aj čas bez časového pásma
  • Okamžité - predstavuje presný časový bod v milisekundách od jávskej epochy z rokov 1970-01-01T00: 00: 00Z
  • Trvanie - predstavuje trvanie v milisekundách medzi 2 bodmi v čase
  • Obdobie - podobný Trvanie, ale umožňujúci prístup k jednotlivým komponentom objektu dátumu a času, ako sú roky, mesiac, dni atď.
  • Interval - predstavuje časový interval medzi 2 okamihmi

Medzi ďalšie dôležité funkcie patrí analyzátory a formátory dátumu. Tieto nájdete v org.joda.time.format balíček.

The kalendárny systém a časové pásmo konkrétne triedy nájdete v dokumente org.joda.time.chrono a org.joda.time.tz balíkov.

Pozrime sa na niekoľko príkladov, v ktorých používame kľúčové vlastnosti Joda-Time na spracovanie dátumu a času.

5. Reprezentujúci dátum a čas

5.1. Aktuálny dátum a čas

Aktuálny dátum bez časových informácií je možné získať použitím teraz () metóda z the LocalDate trieda:

LocalDate currentDate = LocalDate.now ();

Ak potrebujeme iba aktuálny čas, bez informácií o dátume, môžeme použiť Miestny čas trieda:

LocalTime currentTime = LocalTime.now ();

Na získanie a znázornenie aktuálneho dátumu a času bez zohľadnenia časového pásma, môžeme použiť LocalDateTime:

LocalDateTime currentDateAndTime = LocalDateTime.now ();

Teraz, pomocou currentDateAndTime, môžeme ho previesť na iné typy objektov modelovajúcich dátum a čas.

Môžeme získať a Dátum Čas objekt (ktorý zohľadňuje časové pásmo) pomocou metódy toDateTime (). Ak čas nie je potrebný, môžeme ho previesť na a LocalDate metódou toLocalDate (), a keď potrebujeme iba čas, ktorý môžeme využiť toLocalTime () získať a Miestny čas objekt:

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

Všetky vyššie uvedené metódy majú preťaženú metódu, ktorá akceptuje a DateTimeZone objekt pomôžeme nám reprezentovať dátum alebo čas v uvedenom časovom pásme:

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

Joda-Time tiež ponúka vynikajúcu integráciu s Java Date and Time API. Konštruktéri akceptujú a java.util.Date objekt a tiež môžeme použiť randiť() spôsob vrátenia a java.util.Date objekt:

LocalDateTime currentDateTimeFromJavaDate = nový LocalDateTime (nový dátum ()); Dátum currentJavaDate = currentDateTimeFromJavaDate.toDate ();

5.2. Vlastný dátum a čas

Na reprezentáciu vlastného dátumu a času nám Joda-Time poskytuje niekoľko konštruktorov. Môžeme určiť nasledujúce objekty:

  • an Okamžité
  • Java Dátum objekt
  • a String znázornenie dátumu a času pomocou formátu ISO
  • časti dátumu a času: rok, mesiac, deň, hodina, minúta, sekunda, milisekundy
Dátum oneMinuteAgoDate = nový Dátum (System.currentTimeMillis () - (60 * 1000)); Instant oneMinutesAgoInstant = nový Instant (oneMinuteAgoDate); DateTime customDateTimeFromInstant = nový DateTime (oneMinutesAgoInstant); DateTime customDateTimeFromJavaDate = nový DateTime (oneMinuteAgoDate); DateTime customDateTimeFromString = nový DateTime ("2018-05-05T10: 11: 12.123"); DateTime customDateTimeFromParts = nový DateTime (2018, 5, 5, 10, 11, 12, 123); 

Ďalším spôsobom, ako môžeme definovať vlastný dátum a čas, je analýza daného dátumu String znázornenie dátumu a času vo formáte ISO:

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

Môžeme tiež analyzovať vlastné reprezentácie dátumu a času definovaním vlastného DateTimeFormatter:

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

6. Práca s dátumom a časom

6.1. Použitím Okamžité

An Okamžité predstavuje počet milisekúnd od 1970-01-01T00: 00: 00Z do daného časového okamihu. Aktuálny okamih je možné napríklad získať pomocou predvoleného konštruktora alebo metódy teraz ():

Okamžitý okamih = nový Okamžitý (); Okamžité.teraz ();

Ak chcete vytvoriť Okamžité pre vlastný okamih v čase môžeme použiť niektorého z konštruktorov alebo použiť metódy ofEpochMilli () a ofEpochSecond ():

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

Konštruktéri akceptujú a String predstavujúci dátum a čas vo formáte ISO, Java Dátum alebo a dlho hodnota predstavujúca počet milisekúnd od 1970-01-01T00: 00: 00Z:

Instant instantFromString = new Instant ("2018-05-05T10: 11: 12"); Okamžité instantFromDate = nové Okamžité (oneMinuteAgoDate); Instant instantFromTimestamp = new Instant (System.currentTimeMillis () - (60 * 1000));

Keď sú dátum a čas znázornené ako a String máme možnosť analyzovať String pomocou nášho požadovaného formátu:

Okamžité parsedInstant = Instant.parse ("05/05/2018 10:11:12", dateTimeFormatter);

Teraz, keď vieme čo Okamžité predstavuje a ako ho môžeme vytvoriť, pozrime sa, ako sa dá použiť.

Na porovnanie s Okamžité predmety, ktoré môžeme použiť porovnať s() pretože implementuje Porovnateľné môžeme tiež použiť metódy Joda-Time API uvedené v Okamžité čítanie rozhranie ktoré Okamžité tiež implementuje:

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

Ďalšou užitočnou funkciou je to Okamžité možno previesť na a Dátum Čas objekt alebo udalosť Java Dátum:

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

Keď potrebujeme získať prístup k častiam dátumu a času, napríklad roku, hodiny a podobne, môžeme použiť znak dostať () metóda a uveďte a DateTimeField:

int rok = instant.get (DateTimeFieldType.year ()); int mesiac = instant.get (DateTimeFieldType.monthOfYear ()); int day = instant.get (DateTimeFieldType.dayOfMonth ()); int hodina = instant.get (DateTimeFieldType.hourOfDay ());

Teraz, keď sme zakryli Okamžité triedy, pozrime sa na niekoľko príkladov, ako môžeme použiť Trvanie, Obdobie a Interval.

6.2. Použitím Trvanie, Obdobie a Interval

A Trvanie predstavuje čas v milisekundách medzi dvoma časovými bodmi, alebo v tomto prípade to môžu byť dva Okamžité. Použijeme to, keď potrebujeme sčítať alebo odčítať konkrétny čas do alebo od iného Okamžité bez zohľadnenia chronológie a časových pásiem:

long currentTimestamp = System.currentTimeMillis (); dlhé oneHourAgo = currentTimestamp - 24 * 60 * 1000; Trvanie trvania = nové Trvanie (oneHourAgo, currentTimestamp); Okamžité.teraz (). Plus (trvanie);

Môžeme tiež určiť, koľko dní, hodín, minút, sekúnd alebo milisekúnd predstavuje trvanie:

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

Hlavný rozdiel medzi Obdobie a Trvanie je to tak Obdobie je definované z hľadiska jeho zložiek dátumu a času (roky, mesiace, hodiny atď.) a nepredstavuje presný počet milisekúnd. Pri použití Obdobie výpočty dátumu a času zváži časové pásmo a letný čas.

Napríklad pridanie a Obdobie 1 mesiac do 1. februára bude mať za následok reprezentáciu dátumu 1. marca. Používaním Obdobie knižnica zohľadní priestupné roky.

Ak máme použiť a Trvanie výsledok by nebol správny, pretože Trvanie predstavuje pevne stanovený čas, ktorý nezohľadňuje chronológiu ani časové pásma:

Obdobie = nové obdobie (). WithMonths (1); LocalDateTime datePlusPeriod = localDateTime.plus (obdobie);

An Interval, ako uvádza názov, predstavuje dátum a časový interval medzi dvoma pevnými časovými bodmi, ktorý predstavuje dva Okamžité objekty:

Interval interval = new Interval (oneMinuteAgoInstant, instantNow);

Trieda je užitočná, keď potrebujeme skontrolovať, či sa dva intervaly prekrývajú, alebo vypočítať medzeru medzi nimi. The prekrytie () metóda vráti prekrývajúce sa Interval alebo nulový keď sa neprekrývajú:

Okamžitý štartInterval1 = nový Okamžitý ("2018-05-05T09: 00: 00 000"); Okamžitý koniecInterval1 = nový Okamžitý („2018-05-05T11: 00: 00.000“); Interval interval1 = nový Interval (startInterval1, endInterval1); Okamžitý štartInterval2 = nový Okamžitý ("2018-05-05T10: 00: 00.000"); Instant endInterval2 = new Instant ("2018-05-05T11: 00: 00.000"); Interval interval2 = nový Interval (startInterval2, endInterval2); Interval overlappingInterval = interval1.overlap (interval2);

Rozdiel medzi intervalmi je možné vypočítať pomocou vzorca medzera () metódu, a keď chceme vedieť, či sa koniec intervalu rovná začiatku iného intervalu, môžeme použiť znak dosadá () metóda:

assertTrue (interval1.abuts (new Interval (new Instant ("2018-05-05T11: 00: 00.000"), new Instant ("2018-05-05T13: 00: 00.000"))));

6.3. Operácie s dátumom a časom

Medzi najbežnejšie operácie patrí sčítanie, odčítanie a prevod dátumu a času. Knižnica poskytuje špecifické metódy pre každú z tried LocalDate, Miestny čas, LocalDateTimea Dátum Čas. Je dôležité si uvedomiť, že tieto triedy sú nemenné, takže pri každom vyvolaní metódy sa vytvorí nový objekt tohto typu.

Vezmime LocalDateTime pre aktuálny okamih a pokúsiť sa zmeniť jeho hodnotu:

LocalDateTime currentLocalDateTime = LocalDateTime.now ();

Ak chcete do dňa pridať ďalší deň currentLocalDateTime používame plusDays () metóda:

LocalDateTime nextDayDateTime = currentLocalDateTime.plusDays (1);

Môžeme tiež použiť plus() metóda na pridanie a Obdobie alebo Trvanie k nášmu currentLocalDateTime:

Obdobie jeden mesiac = nové obdobie (). S mesiacmi (1); LocalDateTime nextMonthDateTime = currentLocalDateTime.plus (oneMonth);

Metódy sú podobné pre ostatné komponenty dátumu a času, napríklad plusRoky () pre pridanie ďalších rokov, plusSeconds () pre pridanie ďalších sekúnd a tak ďalej.

Odpočítať deň od našich currentLocalDateTime môžeme použiť minusDays () metóda:

LocalDateTime previousDayLocalDateTime = currentLocalDateTime.minusDays (1);

Okrem toho, že robíme výpočty s dátumom a časom, môžeme tiež nastaviť jednotlivé časti dátumu alebo času. Napríklad nastavenie hodiny na 10 je možné dosiahnuť pomocou withHourOfDay () metóda. Ďalšie metódy, ktoré začínajú predponou „S“ možno použiť na nastavenie komponentov daného dátumu alebo času:

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

Ďalším dôležitým aspektom je, že môžeme prevádzať z typu triedy dátumu a času na iný. K tomu môžeme použiť špecifické metódy poskytované knižnicou:

  • toDateTime () - prevádza LocalDateTime do a Dátum Čas objekt
  • toLocalDate () - prevádza LocalDateTime do a LocalDate objekt
  • toLocalTime () - prevádza LocalDateTime na objekt LocalTime
  • randiť() - prevádza LocalDateTime na Javu Dátum objekt

7. Práca s časovými pásmami

Joda-Time nám uľahčuje prácu s rôznymi časovými pásmami a zmenami medzi nimi. Máme DateTimeZone abstraktná trieda, ktorá sa používa na vyjadrenie všetkých aspektov týkajúcich sa časového pásma.

Predvolené časové pásmo používané v Joda-Time je vybrané z user.timezone Vlastnosť systému Java. Knižničné API umožňuje určiť pre každú triedu alebo výpočet individuálne, aké časové pásmo sa má použiť. Napríklad môžeme vytvoriť objekt LocalDateTime

Keď vieme, že v celej aplikácii použijeme konkrétne časové pásmo, môžeme nastaviť predvolené časové pásmo:

DateTimeZone.setDefault (DateTimeZone.UTC);

Od tejto chvíle budú všetky operácie dátumu a času, pokiaľ nie je uvedené inak, zastúpené v časovom pásme UTC.

Metóda slúži na zobrazenie všetkých dostupných časových pásiem getAvailableIDs ():

DateTimeZone.getAvailableIDs ()

Ak potrebujeme reprezentovať dátum alebo čas v konkrétnom časovom pásme, môžeme použiť ktorúkoľvek z tried Miestny čas, LocalDate, LocalDateTime, Dátum Čas a v konštruktore uveďte DateTimeZone objekt:

DateTime dateTimeInChicago = nový DateTime (DateTimeZone.forID ("Amerika / Chicago")); DateTime dateTimeInBucharest = nový DateTime (DateTimeZone.forID ("Európa / Bukurešť")); LocalDateTime localDateTimeInChicago = nový LocalDateTime (DateTimeZone.forID ("Amerika / Chicago"));

Pri konverzii medzi týmito triedami tiež môžeme určiť požadované časové pásmo. Metóda toDateTime () prijíma a DateTimeZone objekt a randiť() prijíma objekt java.util.TimeZone:

DateTime convertedDateTime = localDateTimeInChicago.toDateTime (DateTimeZone.forID ("Európa / Bukurešť")); Dátum prevedenýDátum = localDateTimeInChicago.toDate (TimeZone.getTimeZone ("Európa / Bukurešť"));

8. Záver

Joda-Time je fantastická knižnica, ktorá začala hlavným cieľom vyriešiť problémy v JDK týkajúce sa operácií dátumu a času. Čoskoro sa to stalo de facto knižnica pre manipuláciu s dátumom a časom a nedávno boli hlavné koncepty z nej zavedené v prostredí Java 8.

Je dôležité si uvedomiť, že to autor zvažuje „Byť do značnej miery hotovým projektom“ a odporúča migrovať existujúci kód na použitie implementácie Java 8.

Zdrojový kód článku je k dispozícii na GitHub.


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