Prelazak na novi Java 8 Date Time API

1. Pregled

U ovom ćete uputstvu naučiti kako refaktorizirati svoj kôd kako biste iskoristili novi Date Time API uveden u Javi 8.

2. Novi API ukratko

Rad s datumima na Javi nekada je bio naporan. Stara knjižnica datuma koju je pružio JDK obuhvaćala je samo tri razreda: java.util.Date, java.util.Calendar i java.util.Timezone.

Oni su bili prikladni samo za najosnovnije zadatke. Za bilo što, čak i udaljeno složeno, programeri su morali koristiti biblioteke trećih strana ili napisati tone prilagođenog koda.

Java 8 predstavila je potpuno novi Date Time API (java.util.time. *) koja se slobodno temelji na popularnoj Java knjižnici pod nazivom JodaTime. Ovaj novi API dramatično je pojednostavio obradu datuma i vremena i otklonio mnoge nedostatke stare knjižnice datuma.

1.1. Jasnost API-ja

Prva prednost novog API-a je jasnoća - API je vrlo jasan, sažet i jednostavan za razumijevanje. Nema puno nedosljednosti koje su pronađene u staroj knjižnici, poput numeriranja polja (u kalendaru se mjeseci temelje na nuli, ali dani u tjednu temelje se na jednom).

1.2. API fleksibilnost

Još jedna prednost je fleksibilnost - rad s više prikaza vremena. Stara knjižnica datuma obuhvaćala je samo jednu klasu vremenskog predstavljanja - java.util.Datum, što je unatoč imenu zapravo vremenska oznaka. Pohranjuje samo broj milisekundi proteklih od Unixove ere.

Novi API ima mnogo različitih vremenskih prikaza, svaki prikladan za različite slučajeve upotrebe:

  • Trenutak - predstavlja vremensku točku (vremensku oznaku)
  • LocalDate - predstavlja datum (godinu, mjesec, dan)
  • LocalDateTime - isto kao LocalDate, ali uključuje vrijeme s nanosekundnom preciznošću
  • OffsetDateTime - isto kao LocalDateTime, ali s pomakom vremenske zone
  • Lokalno vrijeme - vrijeme s nanosekundnom preciznošću i bez podataka o datumu
  • ZonedDateTime - isto kao OffsetDateTime, ali uključuje ID vremenske zone
  • OffsetLocalTime - isto kao Lokalno vrijeme, ali s pomakom vremenske zone
  • Mjesec dan - mjesec i dan, bez godine i vremena
  • GodinaMjesec - mjesec i godina, bez dana i vremena
  • Trajanje - količina prikazana u sekundama, minutama i satima. Ima preciznost u nanosekundi
  • Razdoblje - količina prikazana u danima, mjesecima i godinama

1.3. Nepromjenjivost i sigurnost navoja

Još je jedna prednost što su sve vremenske reprezentacije u Java 8 Date Time API nepromjenjiv i tako siguran u nit.

Sve metode mutiranja vraćaju novu kopiju umjesto da mijenjaju stanje izvornog objekta.

Stare klase poput java.util.Datum nisu bili sigurni za konac i mogli su uvesti vrlo suptilne programske pogreške.

1.4. Ulančavanje metoda

Sve metode mutiranja mogu se povezati lancima, što omogućuje provođenje složenih transformacija u jednom retku koda.

ZonedDateTime nextFriday = LocalDateTime.now () .plusHours (1) .with (TemporalAdjusters.next (DayOfWeek.FRIDAY)) .atZone (ZoneId.of ("PST")); 

2. Primjeri

Primjeri u nastavku pokazat će kako izvoditi uobičajene zadatke i sa starim i s novim API-jem.

Dobivanje trenutnog vremena

// Stari datum sada = novi datum (); // Novo ZonedDateTime sada = ZonedDateTime.now (); 

Predstavlja određeno vrijeme

// Stari datum rođenja = novi GregorianCalendar (1990, Kalendar.DECEMBAR, 15) .getTime (); // Novi lokalni datum rođenja = LocalDate.of (1990, mjesec.DECEMBAR, 15); 

Izdvajanje određenih polja

// Stari int mjesec = novi GregorianCalendar (). Get (Calendar.MONTH); // Novi mjesec mjesec = LocalDateTime.now (). GetMonth (); 

Zbrajanje i oduzimanje vremena

// Stari kalendar GregorianCalendar = novi GregorianCalendar (); calendar.add (Calendar.HOUR_OF_DAY, -5); Datum fiveHoursBefore = calendar.getTime (); // Novo LocalDateTime fiveHoursBefore = LocalDateTime.now (). MinusHours (5); 

Izmjena određenih polja

// Stari kalendar GregorianCalendar = novi GregorianCalendar (); calendar.set (Calendar.MONTH, Calendar.JUN); Datum u lipnju = calendar.getTime (); // Novo LocalDateTime inJune = LocalDateTime.now (). WithMonth (Month.JUN.getValue ()); 

Skraćivanje

Skraćivanje resetira sva vremenska polja manja od navedenog polja. U primjeru ispod minute i sve dolje bit će postavljene na nulu

// Stari kalendar sada = Calendar.getInstance (); now.set (Calendar.MINUTE, 0); now.set (Calendar.SECOND, 0); now.set (Calendar.MILLISECOND, 0); Datum skraćen = now.getTime (); // Novo LocalTime skraćeno = LocalTime.now (). TruncatedTo (ChronoUnit.HOURS); 

Pretvorba vremenske zone

// Stari kalendar GregorianCalendar = novi GregorianCalendar (); calendar.setTimeZone (TimeZone.getTimeZone ("CET")); Datum centralEastern = calendar.getTime (); // Novo ZonedDateTime centralEastern = LocalDateTime.now (). AtZone (ZoneId.of ("CET")); 

Dobivanje vremenskog raspona između dvije vremenske točke

// Stari kalendar GregorianCalendar = novi GregorianCalendar (); Datum sada = novi datum (); calendar.add (Calendar.HOUR, 1); Datum hourLater = calendar.getTime (); dugo prošlo = hourLater.getTime () - now.getTime (); // Novo LocalDateTime sada = LocalDateTime.now (); LocalDateTime hourLater = LocalDateTime.now (). PlusHours (1); Raspon trajanja = Duration.bet Between (now, hourLater); 

Oblikovanje i raščlamba vremena

DateTimeFormatter zamjena je za stari SimpleDateFormat koji je siguran za niti i pruža dodatne funkcije.

// Stari SimpleDateFormat dateFormat = novi SimpleDateFormat ("yyyy-MM-dd"); Datum sada = novi datum (); Niz formattedDate = dateFormat.format (sada); Datum parsedDate = dateFormat.parse (formattedDate); // Novi LocalDate sada = LocalDate.now (); DateTimeFormatter formatter = DateTimeFormatter.ofPattern ("yyyy-MM-dd"); Niz formattedDate = now.format (formatter); LocalDate parsedDate = LocalDate.parse (formattedDate, formatter); 

Broj dana u mjesecu

// Kalendar starog kalendara = novi GregorianCalendar (1990, Kalendar.FEBRUAR, 20.); int daysInMonth = calendar.getActualMaximum (Calendar.DAY_OF_MONTH); // Novi int daysInMonth = YearMonth.of (1990, 2) .lengthOfMonth ();

3. Interakcija s naslijeđenim kodom

U mnogim slučajevima korisnik će možda trebati osigurati interoperabilnost s neovisnim knjižnicama koje se oslanjaju na staru knjižnicu datuma.

U Javi 8 stare klase knjižnica datuma proširene su metodama koje ih pretvaraju u odgovarajuće objekte iz novog API-ja datuma.

Nove klase pružaju slične funkcionalnosti.

Instant instantFromCalendar = GregorianCalendar.getInstance (). ToInstant (); ZonedDateTime zonedDateTimeFromCalendar = novi GregorianCalendar (). ToZonedDateTime (); Date dateFromInstant = Date.from (Instant.now ()); GregorianCalendar calendarFromZonedDateTime = GregorianCalendar.from (ZonedDateTime.now ()); Instant instantFromDate = novi datum (). ToInstant (); ZoneId zoneIdFromTimeZone = TimeZone.getTimeZone ("PST"). ToZoneId (); 

4. Zaključak

U ovom smo članku istražili novi API Date Time dostupan u Javi 8. Pogledali smo njegove prednosti u usporedbi s zastarjelim API-jem i na više primjera ukazali na razlike.

Imajte na umu da smo jedva ogrebali površinu mogućnosti novog API-ja Date Time. Svakako pročitajte službenu dokumentaciju kako biste otkrili čitav niz alata koje nudi novi API.

Primjeri koda mogu se naći u projektu GitHub.