Korzystam z java.util.Date
klasy Java w Scali i chcę porównać Date
obiekt z bieżącą godziną. Wiem, że mogę obliczyć różnicę za pomocą getTime ():
(new java.util.Date()).getTime() - oldDate.getTime()
Jednak to pozostawia mi tylko long
reprezentujące milisekundy. Czy istnieje prostszy i przyjemniejszy sposób na uzyskanie delty czasu?
Date
,Calendar
iSimpleDateFormat
”.java.time.Period
i / lubDuration
. Zobacz odpowiedź Basil Bourque poniżej .Odpowiedzi:
Date
Interfejs API JDK jest niestety strasznie zepsuty. Polecam korzystanie z biblioteki Joda Time .Joda Time ma pojęcie przedziału czasu :
EDYCJA: Nawiasem mówiąc, Joda ma dwie koncepcje:
Interval
do reprezentowania przedziału czasu między dwoma momentami czasu (reprezentuje czas między 8 rano a 10 rano) i a,Duration
który reprezentuje czas bez rzeczywistych granic czasowych (np. Reprezentuje dwie godziny!)Jeśli zależy Ci tylko na porównaniach czasu, większość
Date
implementacji (w tym JDK) implementujeComparable
interfejs, który pozwala na użycieComparable.compareTo()
źródło
Comparable.compareTo()
, nieComparable.compare()
.java.time
pakiet w Javie 8 został zainspirowany Joda-Time, ale nie jest zamiennikiem drop-in. Każdy ma swoje zalety i wady. Na szczęście nie musisz wybierać między nimi. Wykorzystaj każdy z nich ze względu na swoje mocne strony, o ile będziesz ostrożny ze swoimiimport
stwierdzeniami. Zobacz inną odpowiedź, na przykład java.time.Prosty plik różnicowy (bez biblioteki lib)
A potem możesz zadzwonić:
aby uzyskać różnicę między 2 datami w jednostkach minut.
TimeUnit
jestjava.util.concurrent.TimeUnit
standardowym wyliczeniem Java przechodzącym od nanosów do dni.Diff czytelny dla człowieka (bez lib)
http://ideone.com/5dXeu6
Wyjście jest coś w rodzaju
Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}
z zamówionymi jednostkami.Musisz tylko przekonwertować tę mapę na ciąg przyjazny dla użytkownika.
Ostrzeżenie
Powyższe fragmenty kodu obliczają prostą różnicę między 2 instancjami. Może to powodować problemy podczas przełączania czasu letniego, jak wyjaśniono w tym poście . Oznacza to, że jeśli obliczasz różnicę między datami bez godziny, możesz mieć brakujący dzień / godzinę.
Moim zdaniem różnica dat jest subiektywna, szczególnie w dni. Możesz:
policz liczbę godzin, które upłynęły: dzień + 1 - dzień = 1 dzień = 24 godziny
policz liczbę upływającego czasu, dbając o oszczędność światła dziennego: dzień + 1 - dzień = 1 = 24h (ale używając północy i czasu letniego może to być 0 dzień i 23 godziny)
policz liczbę
day switches
, co oznacza dzień + 1 1pm - dzień 11 rano = 1 dzień, nawet jeśli upłynął tylko 2 godziny (lub 1 godzina, jeśli jest czas letni: p)Moja odpowiedź jest prawidłowa, jeśli twoja definicja daty różni się w dniach odpowiada 1. przypadkowi
Z JodaTime
Jeśli korzystasz z JodaTime, możesz uzyskać różnicę dla dwóch chwil (millies wspieranych ReadableInstant) z:
Ale możesz także uzyskać różnicę dla lokalnych dat / godzin:
źródło
Pamiętaj, że działa to z datami UTC, więc różnica może być dniem wolnym od pracy, jeśli spojrzysz na lokalne daty. A poprawne działanie z lokalnymi datami wymaga zupełnie innego podejścia ze względu na czas letni.
źródło
(endDate.getTime() - startDate.getTime())
rzutowanie naint
zamiast wyniku końcowego i otrzymujesz przepełnienie liczb całkowitych.Korzystając ze środowiska java.time wbudowanego w Javę 8+:
Wynik:
Aby uzyskać więcej informacji, zobacz samouczek Oracle i standard ISO 8601 .
źródło
Period
zamiastDuration
dat.Musisz jaśniej zdefiniować swój problem. Ty mógł po prostu wziąć liczbę milisekund między dwoma
Date
obiektami i podzielić przez liczbę milisekund w ciągu 24 godzin, na przykład ... ale:Date
zawsze jest w UTCźródło
tl; dr
Konwersja przestarzałych
java.util.Date
obiektów do ich wymiany,java.time.Instant
. Następnie oblicz czas, który upłynął jakoDuration
.Format ISO 8601:
PnYnMnDTnHnMnS
Rozsądna norma ISO 8601 definiuje zwięzłą tekstową reprezentację przedziału czasu jako liczbę lat, miesięcy, dni, godzin itp. Norma określa taki przedział czasu . Format oznacza,
PnYnMnDTnHnMnS
żeP
oznacza „okres”,T
oddziela część daty od części czasu, a pomiędzy nimi są liczby, po których następuje litera.Przykłady:
P3Y6M4DT12H30M5S
trzy lata, sześć miesięcy, cztery dni, dwanaście godzin, trzydzieści minut i pięć sekund
PT4H30M
Cztery i pół godziny
java.time
Java.time ramy wbudowany w Java 8 i później wypiera kłopotliwe stare
java.util.Date
/java.util.Calendar
klas. Nowe klasy inspirowane są bardzo udanym frameworkiem Joda-Time , przeznaczonym jako jego następca, podobnym w koncepcji, ale przebudowanym. Zdefiniowane przez JSR 310 . Rozszerzony o projekt ThreeTen-Extra . Zobacz samouczek .Za chwilę
Instant
Klasa reprezentuje moment na osi czasu w UTC z rozdzielczością nanosekund (do dziewięciu (9) cyfr ułamka dziesiętnego).Najlepiej unikać klas starszych, takich jak
Date
/Calendar
. Ale jeśli musisz współpracować ze starym kodem, który nie został jeszcze zaktualizowany do java.time , konwertuj tam iz powrotem. Wywołaj nowe metody konwersji dodane do starych klas. Aby przejść z Ajava.util.Date
do AInstant
, zadzwońDate::toInstant
.Przedział czasu
Klasy java.time podzieliły ideę reprezentowania przedziału czasu jako liczby lat, miesięcy, dni, godzin, minut, sekund na dwie połowy:
Period
przez lata, miesiące, dniDuration
przez dni, godziny, minuty, sekundyOto przykład.
Zrzut do konsoli.
Oba
Period
iDuration
używają standardu ISO 8601 do generowania ciągu reprezentującego ich wartość.Java 9 dodaje metody do
Duration
uzyskać część dni, część godzin, część minut i część sekund.Możesz uzyskać łączną liczbę dni, godzin, minut lub sekund lub milisekund lub nanosekund w całym okresie trwania.
W Javie 9
Duration
klasa otrzymuje nowe metody zwracania różnych części dni, godzin, minut, sekund, milisekund / nanosekund. Wywołaćto…Part
metody:toDaysPart()
,toHoursPart()
, i tak dalej.ChronoUnit
Jeśli zależy ci tylko na prostszym, większym ziarnistości czasu, takim jak „liczba dni, które upłynęły”, użyj
ChronoUnit
wyliczenia.Inny przykład.
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 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 .
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 .Joda-Time
AKTUALIZACJA: Projekt Joda-Time jest teraz w trybie konserwacji , a zespół doradza migrację do klas java.time . Zostawiam tę sekcję nietkniętą dla historii.
Biblioteka Joda-Time używa ISO 8601 jako wartości domyślnej. Jej
Period
klasa Analizuje i generuje te PnYnMnDTnHnMnS sznurki.Renderuje:
źródło
Period
,Duration
orazChronoUnit
trzy klasy, których celem jest określenie delty między punktami czasu. Proszę wskazać, które części mojej „ściany tekstu” są nieistotne. I nie ma racji, mówiąc, że Pytanie zadało „deltę między datami”: Pytanie zadało deltę międzyDate
obiektami, które są momentami data-czas, a nie „datami”, pomimo niefortunnego nazywania tej klasy.java.util.Date
na aInstant
(tylko wywołanie.toInstant
). I dodałemMoment
sekcję do wyjaśnienia. Wspomniałeś o parzeDate
obiektów, ale w rzeczywistości Pytanie wykorzystuje tylko jeden istniejącyDate
obiekt, a następnie przechwytuje bieżący moment, więc zrobiłem to samo. Dzięki za opinie! Wskazówka: zrezygnuj z używaniaDate
- te starsze klasy są naprawdę okropnym nieszczęsnym bałaganem.https://www.joda.org/joda-time/faq.html#datediff
źródło
Nieco prostsza alternatywa:
Co do „ładniejszego”: cóż, czego dokładnie potrzebujesz? Problem z reprezentowaniem czasu trwania jako liczby godzin i dni itp. Polega na tym, że może to prowadzić do niedokładności i błędnych oczekiwań ze względu na złożoność dat (np. Dni mogą mieć 23 lub 25 godzin z powodu czasu letniego).
źródło
Korzystanie z podejścia milisekundowego może powodować problemy w niektórych lokalizacjach.
Weźmy na przykład różnicę między dwiema datami 03/24/2007 i 03/25/2007 powinna wynosić 1 dzień;
Jednak korzystając z trasy milisekundowej otrzymasz 0 dni, jeśli uruchomisz ją w Wielkiej Brytanii!
Lepszym sposobem na wdrożenie tego jest użycie java.util.Calendar
źródło
Istnieje wiele sposobów na znalezienie różnicy między datami i godzinami. Jednym z najprostszych znanych mi sposobów jest:
Instrukcja print jest tylko przykładem - możesz ją sformatować w dowolny sposób.
źródło
Ponieważ wszystkie odpowiedzi tutaj są poprawne, ale używają starszych bibliotek Java lub innych firm, takich jak Joda lub podobne, po prostu upuszczę inny sposób, używając nowych klas java.time w Javie 8 i nowszych. Zobacz samouczek Oracle .
Użyj
LocalDate
iChronoUnit
:źródło
Odejmowanie daty w milisekundach prac (jak opisano w innym poście), ale trzeba mieć do korzystania HOUR_OF_DAY a nie godziny, kiedy czyszcząc części czasie swojego terminach:
źródło
Jeśli nie chcesz używać JodaTime lub podobnego, najlepszym rozwiązaniem jest prawdopodobnie:
Liczba ms na dzień nie zawsze jest taka sama (z powodu czasu letniego i sekund przestępnych), ale jest bardzo bliska, a co najmniej odchylenia z powodu czasu letniego anulowane na dłuższe okresy. Dlatego dzielenie, a następnie zaokrąglanie da poprawny wynik (przynajmniej o ile lokalny kalendarz nie zawiera dziwnych skoków czasu innych niż czas letni i sekundy przestępne).
Należy pamiętać, że nadal zakłada to
date1
idate2
są ustawione na tę samą porę dnia. Jak podkreśla Jon Skeet, dla różnych pór dnia musisz najpierw zdefiniować, co oznacza „różnica dat”.źródło
date1.getTime()
vsdate2.getTime()
. Różnicując 2016-03-03 na 31.03.2016, obliczymy 27 dni, podczas gdy chcesz 28 dni.Math.round()
, która wydaje się bezpieczna w „prawdziwym świecie” kalendarzy. Przepraszam za hałas.Spójrz na Joda Time , który jest ulepszonym interfejsem API Data / Czas dla Javy i powinien działać dobrze ze Scalą.
źródło
Pokażę różnicę między Joda Interval a Days:
źródło
Jeśli potrzebujesz sformatowanego ciągu zwrotnego, takiego jak „2 dni 03h 42m 07s”, spróbuj tego:
źródło
std
powyższe jest niezdefiniowane.Uwaga: data początkowa i końcowa to -> java.util.Date
i data zakończenia
Podobnie jak w dni, możesz także uzyskać godziny, minuty i sekundy
źródło
Sprawdź przykład tutaj http://www.roseindia.net/java/beginners/DateDifferent.shtml Ten przykład pokazuje różnicę w dniach, godzinach, minutach, sekundach i milisekundach :).
źródło
Użyj strefy czasowej GMT, aby uzyskać instancję kalendarza, ustaw czas za pomocą metody set klasy Calendar. Strefa czasowa GMT ma przesunięcie 0 (niezbyt ważne), a flaga czasu letniego ustawiona na wartość false.
źródło
java.util.Date
itp. Użycie hacka do ustawienia strefy czasowej na GMT powoduje, że kod jest niewrażliwy na efekty czasu letniego.Poniższy kod może dać pożądane wyniki:
źródło
źródło
źródło
Date
, dlatego porównanie to jest najlepsze, jakie można osiągnąć w danych okolicznościach.Najlepszą rzeczą do zrobienia jest
Liczba ta jest liczbą milisekund w ciągu dnia.
Jedna data - druga data daje różnicę w milisekundach.
Zbierz odpowiedź w podwójnej zmiennej.
źródło
Oto poprawne rozwiązanie Java 7 w O (1) bez żadnych zależności.
źródło
Jest to prawdopodobnie najprostszy sposób na zrobienie tego - być może dlatego, że już od jakiegoś czasu programuję w Javie (z jej niewygodnymi bibliotekami daty i czasu), ale ten kod wydaje mi się „prosty i miły”!
Czy jesteś zadowolony z tego, że wynik jest zwracany w milisekundach, czy też jest częścią pytania, które wolisz, aby zwracano go w innym formacie?
źródło
Nie używa standardowego interfejsu API, nie. Możesz rzucić własny, robiąc coś takiego:
Lub możesz użyć Jody :
źródło
Aby odpowiedzieć na pierwsze pytanie:
Umieść następujący kod w funkcji takiej jak Long getAge () {}
Najważniejsze tutaj jest praca z długimi liczbami podczas mnożenia i dzielenia. I oczywiście przesunięcie, które Java stosuje w swoim rachunku dat.
:)
źródło
Ponieważ pytanie jest oznaczone Scalą,
źródło
Po przejrzeniu wszystkich pozostałych odpowiedzi, aby zachować typ daty Java 7, ale być bardziej precyzyjnym / standardowym w przypadku podejścia różnicowego Java 8,
źródło
Spróbuj tego:
możesz edytować ciąg w param () param metod.
źródło