Különbség a Java két dátuma között

1. Áttekintés

Ebben a gyors írásban a Java két dátum közötti különbség kiszámításának több lehetőségét is megvizsgáljuk.

2. Core Java

2.1. Használata java.util.Dátum hogy megtaláljuk a különbséget napokban

Kezdjük azzal, hogy a Java Java API-kat használjuk a számítás elvégzéséhez és a két dátum közötti napok számának meghatározásához:

@Test public void givenTwoDatesBeforeJava8_whenDifferencing_thenWeGetSix () dobja a ParseException {SimpleDateFormat sdf = új SimpleDateFormat ("HH / nn / éééé", Locale.HUN); Date firstDate = sdf.parse ("2017.06.24."); Dátum secondDate = sdf.parse ("2017.06.06."); hosszú diffInMillies = Math.abs (secondDate.getTime () - firstDate.getTime ()); hosszú diff = TimeUnit.DAYS.convert (diffInMillies, TimeUnit.MILLISECONDS); assertEquals (6, diff); }

2.2. Használata java.time.temporal.ChronoUnit hogy megtalálja a különbséget

A Time API a Java 8-ban a dátum-idő egységét képviseli, pl. másodperc vagy nap, a TemporalUnit felület. Minden egység biztosítja a megnevezett módszer megvalósítását között két időbeli objektum közötti idő kiszámításához az adott egység alapján.

Például a kettő közötti másodperc kiszámításához LocalDateTimes:

@Test public void givenTwoDateTimesInJava8_whenDifferiatingInSeconds_thenWeGetTen () {LocalDateTime now = LocalDateTime.now (); LocalDateTime tenSecondsLater = now.plusSeconds (10); long diff = ChronoUnit.SECONDS.bween (most, tízSecondsLater); assertEquals (10, diff); }

ChronoUnit konkrét időegység-készletet biztosít a TemporalUnit felület. Nagyon ajánlott statikus import a ChronoUnitenum értékek a jobb olvashatóság elérése érdekében:

statikus importálás: java.time.temporal.ChronoUnit.SECONDS; // kihagyva a hosszú diff = SECONDS.between (most, tízSecondsLater);

Továbbá bármely két kompatibilis időbeli objektumot átadhatunk a között módszer, még a ZonedDateTime.

Miben nagyszerű ZonedDateTime az, hogy a számítás akkor is működni fog, ha különböző időzónákra vannak beállítva:

@Test public void givenTwoZonedDateTimesInJava8_whenDifferiating_thenWeGetSix () {LocalDateTime ldt = LocalDateTime.now (); ZonedDateTime now = ldt.atZone (ZoneId.of ("Amerika / Montreal")); ZonedDateTime sixMinutesBehind = most .withZoneSameInstant (ZoneId.of ("Ázsia / Szingapúr")) .minusMinutes (6); hosszú diff = ChronoUnit.MINUTES.between (sixMinutesBehind, now); assertEquals (6, diff); } 

2.3. Használata java.time.temporal.Temporal # ig ()

Bármi Időbeli tárgy, mint pl LocalDate vagy ZonedDateTime, biztosít egy amíg módszer az újabb időig eltelt idő kiszámításához Időbeli a megadott egység szempontjából:

@Test public void givenTwoDateTimesInJava8_whenDifferencingInSecondsUsingUntil_thenWeGetTen () {LocalDateTime now = LocalDateTime.now (); LocalDateTime tenSecondsLater = now.plusSeconds (10); hosszú diff = now.illil (tenSecondsLater, ChronoUnit.SECONDS); assertEquals (10, diff); }

A Időbeli # ig és TemporalUnit # között két különböző API ugyanazon funkcionalitáshoz.

2.4. Használata java.time.Duration és java.time.Period

A Java 8-ban a Time API két új osztályt vezetett be: Időtartam és Időszak.

Ha két dátum-időpont különbségét időalapú (óra, perc vagy másodperc) időtartam alatt szeretnénk kiszámítani, akkor a Időtartam osztály:

@Test public void givenTwoDateTimesInJava8_whenDifferiating_thenWeGetSix () {LocalDateTime now = LocalDateTime.now (); LocalDateTime sixMinutesBehind = now.minusMinutes (6); Duration duration = Duration.between (now, sixMinutesBehind); hosszú diff = Math.abs (időtartam: percig ()); assertEquals (6, diff); }

Azonban, óvakodnunk kell egy buktatótól, ha megpróbáljuk használni a Időszak osztály két dátum közötti különbség megjelenítésére.

Egy példa gyorsan megmagyarázza. Számítsuk ki a két dátum közötti hány napot a Időszak osztály:

@Test public void givenTwoDatesInJava8_whenUsingPeriodGetDays_thenWorks () {LocalDate aDate = LocalDate.of (2020, 9, 11); LocalDate sixDaysBehind = aDate.minusDays (6); Period period = Period.between (aDate, sixDaysBehind); int diff = Math.abs (period.getDays ()); assertEquals (6, diff); }

Ha lefuttatjuk a fenti tesztet, akkor az sikeres lesz. Azt gondolhatjuk, hogy a Időszak osztály kényelmes megoldani a problémánkat. Eddig jó.

Ha ez a módszer hat nap különbséggel működik, akkor nem fogunk kételkedni abban, hogy 60 napig is működni fog.

Ezután változtassuk meg a 6 a fenti tesztben 60, és nézze meg, mi történik:

@Test public void givenTwoDatesInJava8_whenUsingPeriodGetDays_thenDoesNotWork () {LocalDate aDate = LocalDate.of (2020, 9, 11); LocalDate sixtyDaysBehind = aDate.minusDays (60); Period period = Period.between (aDate, hatvanDaysBehind); int diff = Math.abs (period.getDays ()); assertEquals (60, diff); }

Most, ha újra lefuttatjuk a tesztet, meglátjuk:

java.lang.AssertionHiba: Várható: 60 Aktuális: 29

Hoppá! Miért tette a Időszak osztály jelentse a különbséget 29 napok?

Ez azért van, mert a Időszak osztály dátumalapú időt jelent a következő formátumban:x év, y hónap és z nap“. Amikor annak hívjuk getDays () metódus, csak a „z nap" rész.

Ezért a időszak A fenti teszt objektumának értéke: „0 év, 1 hónap és 29 nap“:

@Test public void givenTwoDatesInJava8_whenUsingPeriod_thenWeGet0Year1Month29Days () {LocalDate aDate = LocalDate.of (2020, 9, 11); LocalDate sixtyDaysBehind = aDate.minusDays (60); Period period = Period.between (aDate, hatvanDaysBehind); int évek = Math.abs (időszak.getYears ()); int hónapok = Math.abs (period.getMonths ()); int napok = Math.abs (period.getDays ()); assertArrayEquals (új int [] {0, 1, 29}, új int [] {év, hónap, nap}); }

Ha a Java 8 Idő API-jával szeretnénk kiszámolni a napok közötti különbséget, akkor a ChronoUnit.DAYS. között () módszer a legegyszerűbb módszer.

3. Külső könyvtárak

3.1. JodaTime

Ezzel viszonylag egyszerű megvalósítást is végezhetünk JodaTime:

 joda-idő joda-idő 2.9.9 

A Joda-time legújabb verzióját a Maven Central webhelyről szerezheti be.

LocalDate ügy:

@Test public void givenTwoDatesInJodaTime_whenDifferencing_thenWeGetSix () {org.joda.time.LocalDate now = org.joda.time.LocalDate.now (); org.joda.time.LocalDate sixDaysBehind = now.minusDays (6); long diff = Math.abs (Days.daysBetween (now, sixDaysBehind) .getDays ()); assertEquals (6, diff); } 

Hasonlóképpen a LocalDateTime ez:

@Test public void givenTwoDateTimesInJodaTime_whenDifferencing_thenWeGetSix () {org.joda.time.LocalDateTime now = org.joda.time.LocalDateTime.now (); org.joda.time.LocalDateTime sixMinutesBehind = now.minusMinutes (6); hosszú diff = Math.abs (Percek.percek között (most, hatMinutesBehind) .getMinutes ()); assertEquals (6, diff); } 

3.2. Dátum4J

Dátum4j egyenes és egyszerű megvalósítást is biztosít, anélkül, hogy megjegyeznénk, hogy ebben az esetben kifejezetten meg kell adnunk a Időzóna.

Kezdjük a Maven-függőséggel:

 com.darwinsys hirondelle-date4j 1.5.1 

Itt van egy gyors teszt a szabvány használatával Dátum idő:

@Test public void givenTwoDatesInDate4j_whenDifferencing_thenWeGetSix () {DateTime now = DateTime.now (TimeZone.getDefault ()); DateTime sixDaysBehind = now.minusDays (6); hosszú diff = Math.abs (most.numDaysFrom (sixDaysBehind)); assertEquals (6, diff); }

4. Következtetés

Ebben az oktatóanyagban néhány módszert szemléltettünk a dátumok közötti különbség kiszámítására (idővel és idő nélkül), mind egyszerű Java-ban, mind külső könyvtárak használatával.

A cikk teljes forráskódja elérhető a GitHub oldalon.