Jak uzyskać godzinę rozpoczęcia i zakończenia dnia?
taki kod nie jest dokładny:
private Date getStartOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 0, 0, 0);
return calendar.getTime();
}
private Date getEndOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 23, 59, 59);
return calendar.getTime();
}
Nie jest dokładna co do milisekundy.
Odpowiedzi:
tl; dr
Początek dnia
Uzyskaj pełny obraz dnia dzisiejszego w strefie czasowej.
Korzystanie z podejścia Half-Open, w którym początek jest włączający, a koniec wyłączny . Takie podejście rozwiązuje lukę w kodzie, która nie uwzględnia ostatniej sekundy dnia.
Zobacz te same momenty w UTC.
Jeśli chcesz, aby data była wyświetlana przez cały dzień w UTC, a nie w strefie czasowej, użyj
OffsetDateTime
.Te
OffsetDateTime
obiekty będą już w UTC, ale możesz wywołać,toInstant
jeśli potrzebujesz takich obiektów, które z definicji zawsze znajdują się w UTC.Wskazówka: możesz być zainteresowany dodaniem biblioteki ThreeTen-Extra do swojego projektu, aby użyć jej
Interval
klasy do reprezentowania tej paryInstant
obiektów. Daje to klasa użytecznych metod porównywania takich jakabuts
,overlaps
,contains
i więcej.Wpół otwarty
Odpowiedź przez mprivat jest poprawna. Chodzi mu o to, aby nie próbować uzyskać końca dnia, ale raczej porównać to z „przed rozpoczęciem następnego dnia”. Jego pomysł znany jest jako podejście „Half-Open”, w którym okres czasu ma początek obejmujący, a koniec wyłączny .
Czas Joda- 2.3 oferuje metodę tego samego celu, do otrzymania pierwszej chwili dnia:
withTimeAtStartOfDay()
. Podobnie w java.time,LocalDate::atStartOfDay
.Wyszukaj w StackOverflow „joda półotwarta”, aby zobaczyć więcej dyskusji i przykładów.
Zobacz ten post, Przedziały czasowe i inne zakresy powinny być w połowie otwarte , autorstwa Billa Schneidera.
Unikaj starszych klas daty i godziny
Klasy java.util.Date i .Calendar są notorycznie kłopotliwe. Unikaj ich.
Użyj klas java.time . Java.time ramy jest oficjalnym następcą bardzo udanego Joda-Time bibliotece.
java.time
Struktura java.time jest wbudowana w Javę 8 i nowsze. Z powrotem przeniesiony do Java 6 i 7 w projekcie ThreeTen-Backport , dodatkowo dostosowany do Androida w projekcie ThreeTenABP .
Na
Instant
osi czasu znajduje się moment w UTC z rozdzielczością nanosekund .Zastosuj strefę czasową, aby uzyskać czas na zegarze ściennym dla niektórych miejscowości.
Aby uzyskać pierwszy moment dnia, przejdź przez
LocalDate
zajęcia i ichatStartOfDay
metodę.Korzystając z podejścia Half-Open, uzyskaj pierwszą chwilę następnego dnia.
Obecnie framework java.time nie posiada
Interval
klasy opisanej poniżej dla Joda-Time. Jednak projekt ThreeTen-Extra rozszerza java.time o dodatkowe klasy. Ten projekt jest poligonem doświadczalnym dla ewentualnych przyszłych dodatków do java.time. Wśród jego klas jestInterval
. Skonstruuj anInterval
, przekazując paręInstant
obiektów. Możemy wyodrębnićInstant
z naszychZonedDateTime
obiektów.Informacje o java.time
Struktura java.time jest wbudowana w Javę 8 i nowsze. Klasy te kłopotliwe zastąpić stary starszych klas Date-Time, takich jak
java.util.Date
,Calendar
, iSimpleDateFormat
.Aby dowiedzieć się więcej, zobacz samouczek Oracle . I przeszukaj Stack Overflow, aby znaleźć wiele przykładów i wyjaśnień. Specyfikacja to JSR 310 .
Projekt Joda-Time , obecnie w trybie konserwacji , zaleca migrację do klas java.time .
Możesz wymieniać obiekty java.time bezpośrednio ze swoją bazą danych. Użyj sterownika JDBC zgodnego z JDBC 4.2 lub nowszym. Nie ma potrzeby stosowania ciągów ani
java.sql.*
klas. Hibernate 5 i JPA 2.2 obsługują java.time .Skąd wziąć klasy java.time?
Joda-Time
UPDATE: Projekt Joda-Time jest teraz w trybie konserwacji i zaleca migrację do klas java.time . Zostawiam tę sekcję nietkniętą dla historii.
Joda-Time ma trzy klasy do reprezentowania okres czasu na różne sposoby:
Interval
,Period
, iDuration
. AnInterval
ma określony początek i koniec na osi czasu Wszechświata. To pasuje do naszej potrzeby reprezentowania „dnia”.Nazywamy tę metodę
withTimeAtStartOfDay
zamiast ustawiania pory dnia na zera. Z powodu czasu letniego i innych anomalii pierwsza chwila dnia może nie nadejść00:00:00
.Przykładowy kod wykorzystujący Joda-Time 2.3.
Jeśli musisz, możesz przekonwertować plik na java.util.Date.
źródło
LocalDateTime
Java 8
Aktualizacja : dodałem te dwie metody do moich klas narzędzi Java tutaj
Znajduje się w centralnym repozytorium Maven pod adresem:
Java 7 i starsze
Dzięki Apache Commons
Bez Apache Commons
źródło
getStartOfDay
powinno być:LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
Tj. LocalTime, a nie LocalDateTime.getEndOfDay(Date date)
.getStartOfDay(Date date)
metody w sekcji Java 8 są poprawne, a mianowicie LocalDateTime.MAX i .MIN podają najwcześniejszą możliwą datę w przeszłości i w przyszłości, a nie początek i koniec dnia. Zamiast tego sugerowałbym .atStartOfDay () na początek i .plusDays (1) .atStartOfDay (). MinusNanos (1) na koniec.localDateTimeToDate(LocalDateTime startOfDay)
zgłasza wyjątek - java.lang.IllegalArgumentException: java.lang.ArithmeticException: long overfloww getEndOfDay możesz dodać:
Chociaż mówiąc matematycznie, nie możesz określić końca dnia inaczej niż mówiąc, że jest to „przed początkiem następnego dnia”.
Więc zamiast mówić,
if(date >= getStartOfDay(today) && date <= getEndOfDay(today))
powinieneś powiedzieć:if(date >= getStartOfDay(today) && date < getStartOfDay(tomorrow))
. To znacznie bardziej solidna definicja (i nie musisz się martwić o dokładność milisekund).źródło
java.time
Korzystanie z
java.time
frameworka wbudowanego w Javę 8.źródło
Local…
zajęcia nie mają pojęcia stref czasowych oraz dostosowanie do anomalii. Na przykład w niektórych strefach czasowych o północy następuje zmiana czasu letniego, więc pierwsza pora dnia przypada o godzinie01:00:00.0
1:00, a nie o godzinie określonej00:00:00.0
przez ten kod. UżyjZonedDateTime
zamiast tego.Dodatkowym sposobem znalezienia początku dnia za pomocą java8 java.time.ZonedDateTime zamiast przechodzenia przez nie
LocalDateTime
jest po prostu obcięcie wejścia ZonedDateTime do DAYS:źródło
W przypadku języka Java 8 działają następujące instrukcje jednowierszowe. W tym przykładzie używam strefy czasowej UTC. Rozważ zmianę aktualnie używanej strefy czasowej.
Jeśli nie ma różnicy czasu z wyjściem. Próbować:
ZoneOffset.ofHours(0)
źródło
toInstant
jest nielegalną składnią i koncepcyjnie zbędne.Java 8 lub ThreeTenABP
ZonedDateTime
LocalDateTime
Mam nadzieję, że to komuś pomoże.
źródło
Wypróbowałem ten kod i działa dobrze!
źródło
ZonedDateTime
iInstant
masz do dyspozycji, nie musisz nigdy go używaćjava.sql.Timestamp
. Ta klasa jest jedną z okropnych klas starszych, obecnie wypieranych przez klasy java.time . Od wersji JDBC 4.2 możemy bezpośrednio wymieniać obiekty java.time z bazą danych. Twoje mieszanie klas tradycyjnych i nowoczesnych nie ma dla mnie sensu.Innym rozwiązaniem niezależnym od frameworka jest:
Zauważ, że zwraca czas oparty na UTC
źródło
calendar.setTimeInMillis (0); zapewnia dokładność do milisekund
źródło
Wiem, że jest trochę późno, ale w przypadku Java 8, jeśli używasz OffsetDateTime (która oferuje wiele zalet, takich jak TimeZone, Nanoseconds itp.), Możesz użyć następującego kodu:
źródło
Miałem kilka niedogodności ze wszystkimi rozwiązaniami, ponieważ potrzebowałem typu zmiennej Instant i Strefy Czasowej zawsze ingerowałem w zmianę wszystkiego, a następnie łącząc rozwiązania stwierdziłem, że to dobra opcja.
i mamy w rezultacie
Mam nadzieję, że Ci to pomoże
źródło
Instant
obiektów. Wskazówka: możesz być zainteresowany dodaniem biblioteki ThreeTen-Extra do swojego projektu, aby używać jejInterval
klasy.Myślę, że najłatwiej byłoby coś takiego:
Te milisekundy można następnie przekształcić w kalendarz, natychmiastową lub lokalną datę zgodnie z wymaganiami za pomocą czasu Joda.
źródło
źródło