Migrering til den nye Java 8 Date Time API

1. Oversigt

I denne vejledning lærer du, hvordan du omlægger din kode for at udnytte den nye Date Time API, der blev introduceret i Java 8.

2. Ny overblik over API

Arbejde med datoer i Java plejede at være svært. Det gamle datobibliotek leveret af JDK omfattede kun tre klasser: java.util.Date, java.util.Kalender og java.util.Timezone.

Disse var kun egnede til de mest basale opgaver. For alt, hvad der endda er eksternt, måtte udviklerne enten bruge tredjepartsbiblioteker eller skrive masser af brugerdefineret kode.

Java 8 introducerede en helt ny Date Time API (java.util.time. *), der er løst baseret på det populære Java-bibliotek kaldet JodaTime. Denne nye API forenklede dramatisk behandling af dato og tid og fik fast mange mangler ved det gamle datobibliotek.

1.1. API-klarhed

En første fordel ved den nye API er klarhed - API'en er meget klar, kortfattet og let at forstå. Der findes ikke mange uoverensstemmelser i det gamle bibliotek, f.eks. Feltnummerering (i kalendermånederne er nulbaserede, men ugedage er enbaserede).

1.2. API-fleksibilitet

En anden fordel er fleksibilitet - arbejder med flere repræsentationer af tid. Det gamle datobibliotek omfattede kun en enkelt tidsrepræsentationsklasse - java.util.Date, som til trods for sit navn faktisk er et tidsstempel. Den gemmer kun antallet af millisekunder, der er gået siden Unix-epoken.

Den nye API har mange forskellige tidsrepræsentationer, der hver er velegnede til forskellige brugssager:

  • Øjeblikkelig - repræsenterer et tidspunkt (tidsstempel)
  • LocalDate - repræsenterer en dato (år, måned, dag)
  • LocalDateTime - samme som LocalDate, men inkluderer tid med nanosekundpræcision
  • OffsetDateTime - samme som LocalDateTime, men med tidszone forskudt
  • Lokal tid - tid med nanosekund præcision og uden datooplysninger
  • ZonedDateTime - samme som OffsetDateTime, men inkluderer et tidszone-id
  • OffsetLocalTime - samme som Lokal tid, men med tidszone forskudt
  • MånedDag - måned og dag uden år eller tid
  • ÅrMåned - måned og år uden dag eller tid
  • Varighed - den tid, der er repræsenteret i sekunder, minutter og timer. Har nanosekundpræcision
  • Periode - den tid, der er repræsenteret i dage, måneder og år

1.3. Uforanderlighed og trådsikkerhed

En anden fordel er, at alle tidsrepræsentationer i Java 8 Date Time API er uforanderlig og dermed trådsikker.

Alle mutationsmetoder returnerer en ny kopi i stedet for at ændre det originale objekts tilstand.

Gamle klasser såsom java.util.Date var ikke trådsikre og kunne introducere meget subtile samtidige bugs.

1.4. Metodekædning

Alle mutationsmetoder kan lænkes sammen, så det er muligt at implementere komplekse transformationer i en enkelt kodelinje.

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

2. Eksempler

Eksemplerne nedenfor viser, hvordan man udfører almindelige opgaver med både gammel og ny API.

Få aktuel tid

// Gammel dato nu = ny dato (); // Ny ZonedDateTime nu = ZonedDateTime.now (); 

Repræsenterer specifik tid

// Old Date birthDay = new GregorianCalendar (1990, Calendar.DECEMBER, 15) .getTime (); // Ny LocalDate fødselsdag = LocalDate.of (1990, måned. 15. december); 

Uddrag af specifikke felter

// Old int month = new GregorianCalendar (). Get (Calendar.MONTH); // Ny måned måned = LocalDateTime.now (). GetMonth (); 

Tilføje og trække tid

// Gammel gregoriansk kalenderkalender = ny gregoriansk kalender (); calendar.add (Calendar.HOUR_OF_DAY, -5); Dato fiveHoursBefore = calendar.getTime (); // Ny LocalDateTime fiveHoursBefore = LocalDateTime.now (). MinusHours (5); 

Ændring af specifikke felter

// Gammel gregoriansk kalenderkalender = ny gregoriansk kalender (); calendar.set (Calendar.MONTH, Calendar.JUNE); Dato inJuni = kalender.getTid (); // Ny LocalDateTime inJune = LocalDateTime.now (). MedMåned (Måned.JUNE.getValue ()); 

Trunkerende

Afkortning nulstiller alle tidsfelter, der er mindre end det angivne felt. I eksemplet nedenfor vil minutter og alt nedenfor blive nulstillet

// Gammel kalender nu = Calendar.getInstance (); now.set (Calendar.MINUTE, 0); now.set (Calendar.SECOND, 0); now.set (Calendar.MILLISECOND, 0); Afkortet dato = now.getTime (); // Ny LocalTime trunkeret = LocalTime.now (). TruncatedTo (ChronoUnit.HOURS); 

Konvertering af tidszone

// Gammel gregoriansk kalenderkalender = ny gregoriansk kalender (); calendar.setTimeZone (TimeZone.getTimeZone ("CET")); Dato centralEastern = calendar.getTime (); // Ny ZonedDateTime centralEastern = LocalDateTime.now (). AtZone (ZoneId.of ("CET")); 

At få et tidsrum mellem to tidspunkter

// Gammel gregoriansk kalenderkalender = ny gregoriansk kalender (); Dato nu = ny dato (); calendar.add (Calendar.HOUR, 1); Dato hourLater = calendar.getTime (); lang forløbet = hourLater.getTime () - now.getTime (); // Ny LocalDateTime nu = LocalDateTime.now (); LocalDateTime hourLater = LocalDateTime.now (). PlusHours (1); Varighed span = Duration.between (nu, hourLater); 

Tidsformatering og parsing

DateTimeFormatter er en erstatning for den gamle SimpleDateFormat, der er trådsikker og giver yderligere funktionalitet.

// Gammel SimpleDateFormat dateFormat = ny SimpleDateFormat ("åååå-MM-dd"); Dato nu = ny dato (); Streng formattedDate = dateFormat.format (nu); Date parsedDate = dateFormat.parse (formattedDate); // Ny LocalDate nu = LocalDate.now (); DateTimeFormatter formatter = DateTimeFormatter.ofPattern ("åååå-MM-dd"); String formattedDate = now.format (formatter); LocalDate parsedDate = LocalDate.parse (formattedDate, formatter); 

Antal dage i en måned

// Gammel kalenderkalender = ny gregoriansk kalender (1990, kalender. FEBRUAR, 20.) int daysInMonth = kalender.getActualMaximum (Calendar.DAY_OF_MONTH); // Nye int dageInMonth = YearMonth.of (1990, 2) .lengthOfMonth ();

3. Interaktion med ældre kode

I mange tilfælde kan en bruger muligvis sikre interoperabilitet med tredjepartsbiblioteker, der er afhængige af det gamle datobibliotek.

I Java 8 er gamle datobiblioteksklasser udvidet med metoder, der konverterer dem til tilsvarende objekter fra den nye Date API.

Nye klasser giver lignende funktioner.

Øjeblikkelig instantFromCalendar = GregorianCalendar.getInstance (). ToInstant (); ZonedDateTime zonedDateTimeFromCalendar = ny gregoriansk kalender (). TilZonedDateTime (); Dato dateFromInstant = Date.from (Instant.now ()); GregorianCalendar calendarFromZonedDateTime = GregorianCalendar.from (ZonedDateTime.now ()); Øjeblikkelig instantFromDate = ny dato (). Til øjeblikkelig (); ZoneId zoneIdFromTimeZone = TimeZone.getTimeZone ("PST"). ToZoneId (); 

4. Konklusion

I denne artikel udforskede vi den nye Date Time API, der er tilgængelig i Java 8. Vi kiggede på fordelene sammenlignet med den forældede API og påpegede forskelle ved hjælp af flere eksempler.

Bemærk, at vi næppe ridsede overfladen af ​​funktionerne i den nye Date Time API. Sørg for at læse gennem den officielle dokumentation for at finde det fulde udvalg af værktøjer, der tilbydes af den nye API.

Kodeeksempler kan findes i GitHub-projektet.