Czy ktoś mógłby doradzić na temat obecnych najlepszych praktyk Date
i Calendar
typów.
Podczas pisania nowego kodu, jest to najlepiej zawsze faworyzują Calendar
nad Date
lub istnieją okoliczności, w których Date
jest bardziej odpowiedni typ danych?
java.util.Date
,java.util.Calendar
ijava.text.SimpleDateFormat
są teraz Legacy, wyparta przez java.time klas. Wiele funkcji java.time zostało przeniesionych z powrotem do Java 6 i Java 7 w projekcie ThreeTen-Backport . Dalsze dostosowanie do wcześniejszego Androida w projekcie ThreeTenABP . Zobacz Jak korzystać z ThreeTenABP… .Odpowiedzi:
Data jest prostszą klasą i jest tam głównie ze względu na kompatybilność wsteczną. Jeśli chcesz ustawić określone daty lub wykonać arytmetykę dat, użyj kalendarza. Kalendarze obsługują również lokalizację. Poprzednie funkcje manipulowania datą w Data były już nieaktualne.
Osobiście używam albo czasu w milisekundach jako długiego (lub odpowiednio Długiego) lub Kalendarza, kiedy jest wybór.
Zarówno data, jak i kalendarz są zmienne, co może powodować problemy podczas korzystania z interfejsu API.
źródło
java.util.Date
,java.util.Calendar
ijava.text.SimpleDateFormat
są teraz spuścizną , wyparte przez klasy java.time wbudowane w Javę 8 i nowsze wersje . Zobacz samouczek Oracle .Najlepszym sposobem na nowy kod (jeśli Twoje zasady zezwalają na kod innej firmy) jest użycie biblioteki Joda Time .
Zarówno Date, jak i Calendar mają tak wiele problemów projektowych, że żadne z nich nie jest dobrym rozwiązaniem dla nowego kodu.
źródło
Date
iCalendar
są tak naprawdę tą samą podstawową koncepcją (obie reprezentują moment w czasie i są owijane wokół podstawowejlong
wartości).Można argumentować, że
Calendar
tak naprawdę jest jeszcze bardziej zepsuty niżDate
jest, ponieważ wydaje się, że oferuje konkretne fakty o takich rzeczach, jak dzień tygodnia i pora dnia, natomiast jeśli zmienisz jegotimeZone
właściwość, beton zamieni się w blanszange! Z tego powodu żadne obiekty nie są tak naprawdę przydatne jako magazyn roku-miesiąca-dnia lub pory dnia .Używaj
Calendar
tylko jako kalkulatora, który, jeśli zostanie podanyDate
iTimeZone
obiekty, wykona dla ciebie obliczenia. Unikaj jego używania do wpisywania właściwości w aplikacji.Używaj
SimpleDateFormat
razem zTimeZone
iDate
do generowania ciągów wyświetlania.Jeśli masz ochotę na przygodę, użyj Joda-Time, chociaż jest to niepotrzebnie skomplikowane IMHO i wkrótce zostanie zastąpione przez interfejs API daty JSR-310.
Odpowiedziałem wcześniej, że nie jest trudno rzucić własną
YearMonthDay
klasę, która używaCalendar
pod maską do obliczania daty. Nie podobała mi się ta sugestia, ale nadal uważam, że jest ona ważna, ponieważ Joda-Time (i JSR-310 ) są naprawdę zbyt skomplikowane w większości przypadków użycia.źródło
Data jest najlepsza do przechowywania obiektu daty. Jest to utrwalony, zserializowany ...
Kalendarz jest najlepszy do manipulowania datami.
źródło
java.lang.Long
Zazwyczaj używam Data, jeśli to możliwe. Chociaż można go modyfikować, mutatory są w rzeczywistości przestarzałe. Na koniec zasadniczo zawija długi, który reprezentuje datę / godzinę. I odwrotnie, użyłbym kalendarzy, gdybym musiał manipulować wartościami.
Możesz myśleć o tym w ten sposób: używasz StringBuffer tylko wtedy, gdy potrzebujesz Ciągów, którymi możesz łatwo manipulować, a następnie przekształcić je w Ciągi za pomocą metody toString (). W ten sam sposób korzystam z Kalendarza tylko wtedy, gdy muszę manipulować danymi czasowymi.
Najlepszą praktyką jest używanie obiektów niezmiennych jak najwięcej poza modelem domeny . Znacząco zmniejsza ryzyko wystąpienia jakichkolwiek skutków ubocznych i jest to wykonywane przez kompilator, a nie przez test JUnit. Korzystasz z tej techniki, tworząc prywatne pola końcowe w swojej klasie.
I wracając do analogii StringBuffer. Oto kod, który pokazuje, jak konwertować kalendarz i datę
źródło
Date
/Calendar
używać obiektów niezmienny wzorzec.Date
s powinny być używane jako niezmienne punkty w czasie;Calendar
s są zmienne i mogą być przekazywane i modyfikowane, jeśli musisz współpracować z innymi klasami, aby ustalić ostateczną datę. Rozważ je analogicznie,String
aStringBuilder
zrozumiesz, jak uważam, że powinny być używane.(I tak, wiem, że Data nie jest technicznie niezmienna, ale intencją jest, aby nie była zmienna, a jeśli nic nie wywołuje przestarzałych metod, to tak jest.)
źródło
Date
/Calendar
używać obiektów niezmienny wzorzec. W szczególnościInstant
zastępujejava.util.Date
iZonedDateTime
zastępujeCalendar
/GregorianCalendar
.tl; dr
Unikaj całkowicie tych klas starszych . Zamiast tego użyj klas java.time .
Instant
Date
ZonedDateTime
GregorianCalendar
OffsetDateTime
LocalDateTime
Detale
Odpowiedz przez Ortomala Lokni słusznie sugerują, stosując nowoczesne java.time klas zamiast kłopotliwych starych klas legacy-czasowych (data
Date
,Calendar
itd). Ale ta odpowiedź sugeruje, że niewłaściwa klasa jest równoważna (patrz mój komentarz do tej odpowiedzi).Korzystanie z java.time
Klasy java.time to znaczna poprawa w stosunku do starszych klas data-godzina, różnica między dniem i nocą. Stare klasy są źle zaprojektowane, zagmatwane i kłopotliwe. W miarę możliwości powinieneś unikać starych klas. Ale kiedy musisz przekonwertować na / ze starej / nowej, możesz to zrobić, wywołując nowe metody add do starych klas.
Aby uzyskać więcej informacji na temat konwersji, zobacz mój Odpowiedź i sprytny diagram na inne pytanie. Konwertuj java.util.Date na jaki typ „java.time”? .
Przeszukiwanie stosu przepełnienia daje wiele setek przykładowych pytań i odpowiedzi na temat korzystania z java.time. Ale tutaj jest krótkie streszczenie.
Instant
Uzyskaj aktualny moment dzięki
Instant
.Instant
Klasa reprezentuje moment na osi czasu w UTC z rozdzielczością nanosekund (do dziewięciu (9) cyfr ułamka dziesiętnego).ZonedDateTime
Aby zobaczyć ten sam jednoczesny moment przez soczewkę zegara ściennego z określonego regionu , zastosuj strefę czasową (
ZoneId
), aby uzyskaćZonedDateTime
.Strefa czasowa
Określ prawidłową nazwę strefy czasowej w formacie
continent/region
, takie jakAmerica/Montreal
,Africa/Casablanca
lubPacific/Auckland
. Nigdy nie używaj 3-4 literowego skrótu, takiego jakEST
lub,IST
ponieważ nie są to prawdziwe strefy czasowe, nie są znormalizowane, a nawet unikalne (!).Offsetowy
Strefa czasowa to historia zmian regionu w przesunięciu względem UTC . Ale czasami dostajesz tylko przesunięcie bez pełnej strefy. W takim przypadku użyj
OffsetDateTime
klasy.Użycie strefy czasowej jest lepsze niż zwykłe przesunięcie.
LocalDateTime
„Lokalny” w
Local…
klasach oznacza dowolną lokalizację, a nie określoną lokalizację. Więc nazwa może być sprzeczna z intuicją.LocalDateTime
,LocalDate
iLocalTime
celowo brakuje jakichkolwiek informacji o przesunięciu lub strefie czasowej. Więc oni nie reprezentują rzeczywistych momentów, są one nie punkty na osi czasu. W razie wątpliwości lub zamieszania użyjZonedDateTime
raczej niżLocalDateTime
. Przeszukaj stos przepełnienia, aby uzyskać więcej dyskusji.Smyczki
Nie należy łączyć obiektów daty i godziny z łańcuchami reprezentującymi ich wartość. Możesz przeanalizować ciąg, aby uzyskać obiekt daty i godziny, i możesz wygenerować ciąg z obiektu daty i godziny. Ale ciąg nigdy nie jest samą datą i godziną.
Dowiedz się o standardowych formatach ISO 8601 , używanych domyślnie w klasach java.time.
O java.time
Środowisko java.time jest wbudowane w Javę 8 i nowsze wersje . Klasy te kłopotliwe zastąpić stary starszych klas Date-Time, takich jak
java.util.Date
,Calendar
, iSimpleDateFormat
.Projekt Joda-Time , teraz w trybie konserwacji , zaleca migrację do klas java.time .
Aby dowiedzieć się więcej, zobacz samouczek Oracle . I przeszukaj stos przepełnienia dla wielu przykładów i wyjaśnień. Specyfikacja to JSR 310 .
Korzystając ze sterownika JDBC zgodnego z JDBC 4.2 lub nowszym, możesz wymieniać obiekty java.time bezpośrednio ze swoją bazą danych. Nie potrzeba ciągów ani klas java.sql. *.
Gdzie można uzyskać klasy java.time?
Projekt ThreeTen-Extra rozszerza java.time o dodatkowe klasy. Ten projekt jest poligonem doświadczalnym dla ewentualnych przyszłych dodatków do java.time. Można znaleźć kilka przydatnych klas tutaj takie jak
Interval
,YearWeek
,YearQuarter
, i więcej .źródło
W Javie 8 należy użyć nowego pakietu java.time .
Obiekty są niezmienne, brane są pod uwagę strefy czasowe i oszczędność światła dziennego.
Możesz utworzyć
ZonedDateTime
obiekt ze staregojava.util.Date
obiektu, takiego jak ten:źródło
LocalDateTime
. Klasa ta celowo traci wszelkie informacje o przesunięciu względem UTC i strefie czasowej. Ta klasa nie jest równoważna jakDate
w UTC iCalendar
ma przypisaną strefę czasową. Zobacz moją odpowiedź i fajny diagram na inne pytanie. Konwertuj java.util.Date na jaki typ „java.time”? .Zawsze opowiadam się za czasem Jody . Dlatego.
EDYCJA: Klasy daty / godziny Java wprowadzone w Javie 8 są teraz preferowanym rozwiązaniem, jeśli można przeprowadzić migrację do Java 8
źródło
Trochę późno na imprezie, ale Java ma nowy interfejs API Data Time w JDK 8. Możesz zaktualizować swoją wersję JDK i zastosować standard. Nigdy więcej niechlujnej daty / kalendarza, żadnych słoików innych firm.
źródło
Data powinna zostać ponownie opracowana. Zamiast być długim intergerem, powinien zawierać rok, miesiąc, datę, godzinę, minutę, sekundę jako osobne pola. Może być nawet dobrze przechowywać kalendarz i strefę czasową, z którą ta data jest powiązana.
W naszej naturalnej rozmowie, jeśli umówimy się na spotkanie w dniu 1 listopada 2013 r. O godzinie 13.00 czasu nowojorskiego, jest to data i godzina. To NIE jest kalendarz. Powinniśmy być w stanie rozmawiać w ten sposób również w Javie.
Gdy data jest przechowywana jako długa liczba całkowita (w miliardach sekund od 1 stycznia 1970 roku lub coś takiego), obliczenie jej bieżącej daty zależy od kalendarza. Różne kalendarze podadzą inną datę. Wynika to z możliwości podania czasu bezwzględnego (np. 1 bilion sekund po Wielkim Wybuchu). Ale często potrzebujemy również wygodnego sposobu rozmowy, takiego jak obiekt podsumowujący rok, miesiąc itp.
Zastanawiam się, czy istnieją nowe postępy w Javie w celu pogodzenia tych 2 celów. Może moja wiedza java jest za stara.
źródło
Date
został ponownie opracowany; zastąpiony przezjava.time.Instant
klasę. ICalendar
/GregorianCalendar
został zastąpiony przezjava.time.ZonedDateTime
klasę.Btw „data” jest zwykle oznaczana jako „przestarzała / przestarzała” (nie wiem dokładnie dlaczego) - coś tam jest napisane tam Java: Dlaczego konstruktor daty jest przestarzały i czego mam używać zamiast tego?
Wygląda na to, że jest to problem konstruktora - tylko przez nową datę (int rok, int miesiąc, int dzień) , zalecany sposób to przez kalendarz i ustaw parametry osobno .. ( Calendar cal = Calendar.getInstance (); )
źródło
Korzystam z Kalendarza, gdy potrzebuję określonych operacji w datach, takich jak przemieszczanie się w czasie, ale Data jest dla mnie pomocna, gdy musisz sformatować datę w celu dostosowania swoich potrzeb, niedawno odkryłem, że Locale ma wiele przydatnych operacji i metod. Korzystam teraz z ustawień regionalnych!
źródło
Calendar
iDate
zajęcia zostały wyparte lata temu przez zajęcia java.time . Nie trzeba nigdy używaćDate
lubCalendar
. ILocale
nie ma nic wspólnego ze znaczeniem obiektów daty i godziny. ALocale
służy tylko do określenia języka ludzkiego i norm kulturowych, które mają być używane podczas lokalizacji podczas generowania tekstu reprezentującego wartość obiektu daty i godziny.