Różnice między Java 8 Date Time API (java.time) i Joda-Time

264

Wiem, że są pytania dotyczące java.util.Date i Joda-Time. Ale po pewnym kopaniu nie mogłem znaleźć wątku na temat różnic między interfejsem API java.time (nowym w Javie 8 , zdefiniowanym przez JSR 310 ) a Joda-Time .

Słyszałem, że java.time API Javy 8 jest znacznie czystsze i może zrobić znacznie więcej niż Joda-Time. Ale nie mogę znaleźć przykładów porównujących oba.

  • Co może zrobić java.time, czego nie potrafi Joda-Time?
  • Co java.time może zrobić lepiej niż Joda-Time?
  • Czy wydajność jest lepsza w java.time?
Zack
źródło
8
Nie dotyczy to Java 7, a nie Java 8. Odpowiedź na to pytanie została zredagowana dla Java 8 z bardzo małymi szczegółami. Moje pytanie dotyczy konkretnie nowego API DateTime Java 8, a nie java.util.Date Java 7. Szukam tylko odpowiedzi, która porówna Java 8 z JodaTime.
Zack
2
być może ten dokument Oracle może ci pomóc.
MarioDS
Jeśli masz Java 7, skorzystaj z dodatkowej biblioteki, jeśli masz Java 8, skorzystaj z wbudowanej biblioteki. Ponieważ obie biblioteki są w zasadzie zaprojektowane przez tę samą osobę, nie jestem pewien, jakich głównych różnic się spodziewasz.
Peter Lawrey,
2
@PeterLawrey: Joda-Time oraz interfejs API daty i godziny Java 8 są zupełnie różne.
jarnbjo
5
Możesz również przeczytać ten post na blogu od Stephena Colbourne'a - głównego autora obu projektów.
Matt Johnson-Pint

Odpowiedzi:

416

Wspólne cechy

a) Obie biblioteki używają niezmiennych typów. Joda-Time oferuje również dodatkowe typy zmienne, takie jak MutableDateTime.

b) Ponadto: Obie biblioteki zostały zainspirowane studiami projektowymi „TimeAndMoney” Erica Evansa lub pomysłami Martina Fowlera na temat stylu opartego na domenie, więc starają się mniej więcej o płynny styl programowania (choć nie zawsze idealny ;-)).

c) W obu bibliotekach otrzymujemy prawdziwy typ daty kalendarza (nazywany LocalDate), prawdziwy typ czasu na ścianie (nazywany LocalTime) i kompozycję (nazywany LocalDateTime). To bardzo duża wygrana w porównaniu ze starymi java.util.Calendari java.util.Date.

d) Obie biblioteki stosują podejście zorientowane na metody, co oznacza, że ​​zachęcają użytkownika do korzystania getDayOfYear()zamiast get(DAY_OF_YEAR). Powoduje to wiele dodatkowych metod w porównaniu z java.util.Calendar(chociaż ta ostatnia nie jest w ogóle bezpieczna dla typu z powodu nadmiernego użycia int).

Występ

Zobacz inną odpowiedź @ OO7 wskazującą na analizę Michaiła Woroncowa, chociaż punkt 3 (wyłapywanie wyjątków) jest prawdopodobnie przestarzały - zobacz ten błąd JDK . Różna wydajność (która jest ogólnie na korzyść JSR-310 ) wynika głównie z faktu, że wewnętrzna implementacja Joda-Time zawsze używa czasu pierwotnego podobnego do czasu maszynowego (w milisekundach).

Zero

Joda-Time często używa NULL jako domyślnej strefy czasowej systemu, domyślnych ustawień regionalnych, bieżącego znacznika czasu itp., Podczas gdy JSR-310 prawie zawsze odrzuca wartości NULL.

Precyzja

JSR-310 obsługuje precyzję nanosekundową, a czas Joda jest ograniczony do precyzji milisekundowej .

Obsługiwane pola:

Przegląd obsługiwanych pól w Javie-8 (JSR-310) jest podawany przez niektóre klasy w pakiecie czasowym (na przykład ChronoField i WeekFields ), podczas gdy Joda-Time jest raczej słaby w tym obszarze - patrz DateTimeFieldType . Największym brakiem Joda-Time jest tutaj brak zlokalizowanych pól związanych z tygodniem. Wspólną cechą obydwu projektów implementacji w terenie jest to, że oba oparte są na wartościach typu long (żadnych innych typów, nawet wyliczeń).

Enum

JSR-310 oferuje wyliczenia takie jak DayOfWeeklub Monthpodczas gdy Joda-Time nie oferuje tego, ponieważ został opracowany głównie w latach 2002-2004 przed Javą 5 .

Strefa API

a) JSR-310 oferuje więcej funkcji strefy czasowej niż Joda-Time. Później nie jest w stanie zapewnić programowego dostępu do historii przejść przesunięcia strefy czasowej, podczas gdy JSR-310 jest w stanie to zrobić.

b) Dla twojej informacji: JSR-310 przeniósł swoje wewnętrzne repozytorium strefy czasowej do nowej lokalizacji i innego formatu. Stary folder biblioteki lib / zi już nie istnieje.

Dostrajacz a własność

JSR-310 wprowadził TemporalAdjusterinterfejs jako sformalizowany sposób uzewnętrznienia obliczeń i manipulacji czasowych, szczególnie dla bibliotek lub twórców frameworków. Jest to miły i względnie łatwy sposób na osadzenie nowych rozszerzeń JSR-310 (rodzaj odpowiednika statycznego pomocnika zajęcia dla byłych java.util.Date).

Jednak dla większości użytkowników ta funkcja ma bardzo ograniczoną wartość, ponieważ ciężar pisania kodu nadal spoczywa na użytkowniku. Wbudowanych rozwiązań opartych na nowej TemporalAdjusterkoncepcji nie jest tak wiele, obecnie istnieje tylko klasa pomocnicza TemporalAdjustersz ograniczonym zestawem manipulacji (oraz wyliczeniami Monthlub innymi typami czasowymi).

Joda-Time oferuje pakiet terenowy, ale praktyka wykazała, że ​​nowe implementacje w terenie są bardzo trudne do kodowania. Z drugiej strony Joda-Time oferuje tak zwane właściwości, które sprawiają, że niektóre manipulacje są znacznie łatwiejsze i bardziej eleganckie niż w JSR-310, na przykład property.withMaximumValue () .

Systemy kalendarza

JSR-310 oferuje 4 dodatkowe systemy kalendarza. Najciekawszym jest Umalqura (używany w Arabii Saudyjskiej). Pozostałe 3 to: Minguo (Tajwan), japoński (tylko współczesny kalendarz od 1871 r.!) I ThaiBuddhist (tylko poprawny po 1940 r.).

Joda-Time oferuje islamski kalendarz oparty na podstawie obliczeniowej - a nie kalendarz oparty na obserwacji, taki jak Umalqura. Tajski-buddyjski jest również oferowany przez Joda-Time w podobnej formie, Minguo i japoński nie. W przeciwnym razie Joda-Time oferuje także kalendarz koptyjski i etiopski (ale bez wsparcia dla internacjonalizacji).

Bardziej interesujące dla Europejczyków: Joda-Time oferuje również kalendarz gregoriański , juliański i mieszany gregoriańsko-julijski. Jednak praktyczna wartość rzeczywistych obliczeń historycznych jest ograniczona, ponieważ ważne funkcje, takie jak historia różnych dat rozpoczęcia roku, nie są w ogóle obsługiwane (ta sama krytyka obowiązuje dla starych java.util.GregorianCalendar).

Inne kalendarze jak hebrajskim lub perski lub Hindu są całkowicie brakuje w obu bibliotekach.

Dni epoki

JSR-310 ma klasę JulianFields, a Joda-Time (wersja 2.0) oferuje pewne metody pomocnicze w klasie DateTimeUtils .

Zegary

JSR-310 nie ma interfejsu (błąd projektowy), ale abstrakcyjną klasę, java.time.Clockktórej można użyć do dowolnego wstrzykiwania zależności zegara. Joda-Time oferuje zamiast tego interfejs MillisProvider i niektóre metody pomocnicze w DateTimeUtils . W ten sposób Joda-Time może również obsługiwać modele testowane z różnymi zegarami (kpiny itp.).

Czas trwania arytmetyki

Obie biblioteki obsługują obliczanie odległości czasowych w co najmniej jednej jednostce czasowej. Jednak podczas obsługi czasów trwania pojedynczych jednostek styl JSR-310 jest oczywiście ładniejszy (i oparty na długim zakresie zamiast używania int):

JSR-310 => long days = ChronoUnit.DAYS.between(date1, date2);

Czas Joda => int days = DAYS.daysBetween(date1, date2).getDays();

Różne są także czasy trwania wielu jednostek. Nawet wyniki obliczeń mogą się różnić - zobacz ten zamknięty problem Joda-Time . Podczas gdy JSR-310 stosuje bardzo proste i ograniczone podejście do korzystania tylko z klas Period(czas trwania oparty na latach, miesiącach i dniach) i Duration(oparty na sekundach i nanosekundach), Joda-Time używa bardziej wyrafinowanego sposobu korzystania z klasy PeriodTypew celu kontroli w których jednostkach należy wyrazić czas trwania (nazywany Joda „okresem”). Podczas, gdyPeriodType-API jest w jakiś sposób niewygodny w użyciu w podobny sposób, że JSR-310 w ogóle go nie oferuje. Szczególnie w JSR-310 nie jest jeszcze możliwe zdefiniowanie mieszanych czasów i dat (np. Na podstawie dni i godzin). Ostrzegaj więc, jeśli chodzi o migrację z jednej biblioteki do drugiej. Omawiane biblioteki są niekompatybilne - pomimo częściowo takich samych nazw klas.

Interwały

JSR-310 nie obsługuje tej funkcji, a Joda-Time ma ograniczone wsparcie. Zobacz także tę odpowiedź SO .

Formatowanie i parsowanie

Najlepszym sposobem na porównanie obu bibliotek jest wyświetlenie klas o takich samych nazwach DateTimeFormatterBuilder (JSR-310) i DateTimeFormatterBuilder (Joda-Time). Wariant JSR-310 jest nieco bardziej wydajny (może również obsługiwać dowolny rodzaj, pod TemporalFieldwarunkiem że implementatorowi pola udało się zakodować niektóre punkty rozszerzenia, takie jak resol () ). Najważniejsza różnica jest jednak - moim zdaniem:

JSR-310 może znacznie lepiej analizować nazwy stref czasowych (symbol wzorca formatu z), podczas gdy Joda-Time nie mógł tego zrobić w swoich wcześniejszych wersjach i teraz tylko w bardzo ograniczony sposób.

Kolejną zaletą JSR-310 jest obsługa samodzielnych nazw miesięcy, co jest ważne w językach takich jak rosyjski lub polski itp. Joda-Time nie ma dostępu do takich zasobów - nawet na platformach Java-8.

Składnia wzoru w JSR-310 jest również bardziej elastyczna niż w Joda-Time, pozwala na opcjonalne sekcje (za pomocą nawiasów kwadratowych), jest bardziej zorientowana na standard CLDR i oferuje wypełnianie (symbol litery p) i więcej pól.

W przeciwnym razie należy zauważyć, że Joda-Time może formatować czasy trwania za pomocą PeriodFormatter . JSR-310 nie może tego zrobić.


Mam nadzieję, że ten przegląd pomaga. Wszystkie zebrane informacje są tam głównie dzięki moim wysiłkom i badaniom, jak zaprojektować i wdrożyć lepszą bibliotekę daty i godziny (nic nie jest idealne).

Aktualizacja z dnia 24.06.2015:

Tymczasem znalazłem czas na napisanie i opublikowanie tabelarycznego przeglądu różnych bibliotek czasu w Javie. Tabele zawierają również porównanie między Joda-Time v2.8.1 i Java-8 (JSR-310). Jest bardziej szczegółowy niż ten post.

Meno Hochschild
źródło
12
To jest wybitny post. Dziękujemy za udostępnienie wszystkich tych informacji. Jeśli wybierzesz między Joda i JSR-310 (tylko w przypadku waniliowych zastosowań), co byś wybrał? Teraz mam do czynienia z tym wyborem. Rozważam JSR-310 tylko dlatego, że jest nowszy i staram się wspierać „posuwanie się naprzód” tam, gdzie to możliwe.
kevinarpe
7
@kevinarpe Gdybym miał tylko wybór między JSR-310 a Joda-Time, prawdopodobnie wolałbym JSR-310, ponieważ Joda-Time prawie wstrzymał dalszy rozwój (nie można oczekiwać nowych dużych funkcji - tylko poprawiania błędów i małych aktualizacji). A konstrukcja JSR-310 jest po prostu bardziej nowoczesna (i ma lepszą jakość wewnętrzną). Nawiasem mówiąc, i nie jest to zaskakujące, moja prawdziwa decyzja woli raczej wybrać własną bibliotekę Time4J - patrz także link do przeglądu tabelarycznego podany na dole mojego postu. Zawsze dobrze jest mieć alternatywy i silnie zależy to od potrzebnych funkcji.
Meno Hochschild
Czy wersja przedziału czasu Java8 nie jest wersją?
Christian Hujer
1
@ChristianHujer Nie, java.time.Durationnie można zapytać o jego początek lub koniec, w przeciwieństwie do interwału zakotwiczonego na osi czasu. Ten typ JSR-310 to tylko para upływających sekund i nanosekund od nieznanego początku.
Meno Hochschild,
42

Java 8 Data / godzina:

  1. Klasy Java 8 są budowane wokół czasu ludzkiego. To sprawia, że ​​są szybkie dla arytmetyki / konwersji danych w czasie.
  2. Programy pobierające datę / czas, takie jak getDayOfMonthmają złożoność O (1) w implementacji Java 8.
  3. Przetwarzanie OffsetDateTime/ OffsetTime/ ZonedDateTimejest bardzo wolne w Javie 8 ea b121 z powodu wyjątków zgłoszonych i przechwyconych wewnętrznie w JDK.
  4. Zestaw pakietów: java.time.*, java.time.chrono.*, java.time.format.*, java.time.temporal.*,java.time.zone.*
  5. Instanty (znaczniki czasu) Data i godzina Częściowa data i czas Parser i formatyzator Strefy czasowe Różne chronologie (kalendarze).
  6. W istniejących klasach występują takie problemy, jak Data nie obsługuje I18N ani L10N. Są zmienne!
  7. Prostsze i bardziej niezawodne.
  8. Zegary można wstrzykiwać.
  9. Zegary mogą być tworzone z różnymi właściwościami - zegary statyczne, fałszywe zegary, zegary o niskiej precyzji (całe sekundy, całe minuty itp.).
  10. Zegary można tworzyć w określonych strefach czasowych. Clock.system(Zone.of("America/Los_Angeles")).
  11. Umożliwia sprawdzenie daty i godziny obsługi kodu.
  12. Uniezależnia testy od strefy czasowej.

Czas Joda:

  1. Joda-Time używa czasu maszynowego w środku. Ręczna implementacja oparta na wartościach int / long byłaby znacznie szybsza.
  2. Osoby pobierające Joda-Time wymagają obliczenia czasu komputer-człowiek przy każdym wywołaniu osoby pobierającej, co czyni Joda-Time wąskim gardłem w takich sytuacjach.
  3. Składa się z niezmiennych klas, które obsługuje Instant, Data i czas, Częściowe i Czas trwania Jest elastyczny Jest dobrze zaprojektowany.
  4. Reprezentuje daty jako natychmiastowe. Ale data i godzina mogą odpowiadać więcej niż jednej chwili. Nakładają się godziny, kiedy kończą się oszczędności światła dziennego. Jak również nie ma żadnej chwili, która by mu odpowiadała. Gap godzina, kiedy zaczyna się światło dzienne. Musi wykonywać złożone obliczenia dla prostych operacji.
  5. Akceptuje wartości null jako prawidłowe wartości w większości metod. Prowadzi do subtelnych błędów.

Bardziej szczegółowe porównanie patrz: -

Wydajność biblioteki daty / godziny Java 8 (a także Joda-Time 2.3 i juCalendar) . & Nowa data i godzina API w Javie 8

OO7
źródło
Gdy powiesz „uniezależnia testy od strefy czasowej”. Co dokładnie masz na myśli?
Zack
@Zack: Prawdopodobnie, jeśli testujesz kod, który zachowuje się inaczej w zależności od strefy czasowej, może być konieczne wymuszenie uruchomienia testu z inną domyślną strefą czasową niż ta, którą zapewnia system operacyjny.
jarnbjo
Hah - myślałem, że powiedziałeś, że Joda działa wewnętrznie na maszynie czasu zamiast na maszynie czasu ... I nie byłbym zaskoczony
Kyranstar
4
@ OO7 Co rozumiesz przez „czas ludzki”? Czas i tak jest obliczany przez maszyny.
IgorGanapolsky
1

Joda-Time jest teraz w trybie konserwacji

Nie jest to bezpośrednia odpowiedź na pytanie, ale projekt Joda-Time nie jest już aktywnie rozwijany. Zespół sugeruje użytkownikom migrację do nowszego interfejsu API java.time . Zobacz samouczek Oracle .

Z oficjalnej strony projektu GitHub :

Czas Joda nie jest już aktywnie rozwijany, z wyjątkiem aktualizowania danych strefy czasowej. Począwszy od Java SE 8, użytkownicy proszeni są o migrację do java.time (JSR-310) - podstawowej części JDK, która zastępuje ten projekt. Dla użytkowników Androida java.time jest dodany w API 26+. Projekty wymagające obsługi niższych poziomów API mogą korzystać z biblioteki ThreeTenABP.

Saikat
źródło