2010-05-26 9 views
7

Mam 2 obiekt daty w bazie danych, które reprezentują godziny pracy firmy.Trudno poradzić sobie z porównywaniem godzin z różnymi strefami czasowymi w Javie?

Potrzebuję tylko godzin, ale ponieważ muszę zapisać datę. wydaje się tak:

Date companyWorkStartHour; 
Date companyWorkEndHour; 

godzina startu: 12-12-2001-13: 00: 00 godzin wykończenie: 12-12-2001-18: 00: 00

mam strefie czasowej firma i użytkownika. (mój serwer może znajdować się w innej strefie czasowej).

TimeZone userTimeZone; 
TimeZone companyTimeZone; 

muszę sprawdzić, czy aktualny czas użytkownika (biorąc pod uwagę jego czasowej) jest w firmie pracuje godzin (biorąc pod uwagę strefę czasową Spółki).

Jak mogę to zrobić? Od ponad tygodnia mam problem z kalendarzem Java i bez powodzenia!

+0

Czy strefa czasowa samej DB jest już brana pod uwagę? Czy godziny są poprawne, gdy wyszukujesz je w bazie danych jako java.sql.Date i drukujesz od razu? – BalusC

+0

Zaleca się ogólne przechowywanie w UTC i tylko konwersję do iz innych stref czasowych dla wprowadzania i prezentacji. Porównanie powinno być proste. 'Date' i jego nowoczesna zamiana' Instant' używają wewnętrznie UTC. –

Odpowiedz

6

Klasa java.util.Date to kontener, który przechowuje liczbę milisekund od 1 stycznia 1970, 00:00:00 UTC. Zauważ, że klasa Date nie wie nic o strefach czasowych. Użyj klasy Calendar, jeśli chcesz pracować z strefami czasowymi. (edycja edycja 19-sty-2017: jeśli używasz Java 8, użyj nowego API daty i czasu w pakiecie java.time).

Klasa Date nie nadaje się do przechowywania numeru godziny (na przykład 13:00 lub 18:00) bez daty. Po prostu nie jest on stworzony do tego celu, więc jeśli spróbujesz go użyć w ten sposób, jak się wydaje, napotkasz na wiele problemów, a twoje rozwiązanie nie będzie eleganckie.

Jeśli zapomnisz o użyciu klasy Date przechowywać godzin pracy i po prostu używać liczb całkowitych, to będzie dużo prostsze:

Date userDate = ...; 
TimeZone userTimeZone = ...; 

int companyWorkStartHour = 13; 
int companyWorkEndHour = 18; 

Calendar cal = Calendar.getInstance(); 
cal.setTime(userDate); 
cal.setTimeZone(userTimeZone); 

int hour = cal.get(Calendar.HOUR_OF_DAY); 
boolean withinCompanyHours = (hour >= companyWorkStartHour && hour < companyWorkEndHour); 

Jeśli też chcesz wziąć minut (nie zaledwie kilka godzin) do konta, mógłby zrobić coś takiego:

int companyWorkStart = 1300; 
int companyWorkEnd = 1830; 

int time = cal.get(Calendar.HOUR_OF_DAY) * 100 + cal.get(Calendar.MINUTE); 
boolean withinCompanyHours = (time >= companyWorkStart && time < companyWorkEnd); 
+0

Dzięki! Twój kod bardzo mi pomógł. Inne powiązane pytanie: Muszę wyświetlać użytkownikowi godzin pracy w strefie czasowej użytkownika. Jak mogę to zrobić, jeśli firmaWorkStartHour i companyWorkEndHour są liczbami całkowitymi? – Riki

+0

@Riki: Sądzę, że te godziny są już w strefie czasowej użytkownika, prawda? Możesz utworzyć 'Kalendarz' i ustawić na nim strefę czasową, tak jak w powyższym kodzie, i możesz ustawić poszczególne pola w' Kalendarz' za pomocą 'set()', na przykład: 'cal.set (Calendar.HOUR_OF_DAY, companyWorkStartHour); '. – Jesper

+0

Tak, masz rację! dopóki mi nie odpowiedziałeś, zrobiłem to samo, co twoja sugestia! – Riki

0

Hej Nie wiem, jak to zrobić, używając kalendarza Java, ale zdecydowanie polecam używanie pakietu Joda Time. Jest to znacznie prostszy system do użycia i zapewnia bezpośrednie metody wyodrębniania wszystkich subkomponentów danych i czasu, a nawet tylko do tworzenia prostych obiektów czasu bez uwzględnienia daty. Wtedy wyobrażam sobie, że byłoby to kwestią porównania 2 różnic w strefie czasowej i odjęcia różnicy od obiektu JodaTime.

+2

Napisz więc przykład, który odpowiada na jego pytanie? Mówienie, że JodaTime jest lepsze, jest łatwe, ponieważ jest to znany fakt, ale jest bezwartościowe, jeśli nie odpowiesz ** na to pytanie. Opublikuj to jako komentarz. – BalusC

0

Nie próbowałem biblioteki Joda. Ten kod powinien zadziałać.

public boolean checkUserTimeZoneOverLaps(TimeZone companyTimeZone, 
     TimeZone userTimeZone, Date companyWorkStartHour, 
     Date companyWorkEndHour, Date userCurrentDate) { 

    Calendar userCurrentTime = Calendar.getInstance(userTimeZone); 
    userCurrentTime.setTime(userCurrentDate); 
    int year = userCurrentTime.get(Calendar.YEAR); 
    int month = userCurrentTime.get(Calendar.MONTH); 
    int day = userCurrentTime.get(Calendar.DAY_OF_MONTH); 

    Calendar startTime = Calendar.getInstance(companyTimeZone); 
    startTime.setTime(companyWorkStartHour); 
    startTime.set(Calendar.YEAR, year); 
    startTime.set(Calendar.MONTH, month); 
    startTime.set(Calendar.DAY_OF_MONTH, day); 

    Calendar endTime = Calendar.getInstance(companyTimeZone); 
    endTime.setTime(companyWorkEndHour); 
    endTime.set(Calendar.YEAR, year); 
    endTime.set(Calendar.MONTH, month); 
    endTime.set(Calendar.DAY_OF_MONTH, day); 

    if (userCurrentTime.after(startTime) && userCurrentTime.before(endTime)) { 
     return true; 
    } 
    return false; 
} 

EDIT uaktualniony kod do zastanowienia komentarzy Bruna. Nie powinny być przyjmowane daty godzin pracy firmy.

+0

Snehal, problem polega na tym, że używasz czasu rozpoczęcia/zakończenia z datą, w której zostały zapisane (np. 12-12-2001). Możesz więc porównywać dzisiejszą datę (od 'userCurrentDate') do 12-12-2001 (z' companyWorkStart/EndHour'). –

+0

Ale czy nie zwróci fałszu, na wypadek gdyby tak się stało? – Snehal

+0

Tak. Ale część daty nie powinna być brana pod uwagę przy porównywaniu w tym przypadku. Interesuje go sprawdzenie, czy aktualny czas użytkownika znajduje się między godziną rozpoczęcia i zakończenia, więc ważna jest tylko część czasu zapisanych zdarzeń companyWorkStart/EndHour. –

2

spróbować czegoś takiego:

Calendar companyWorkStart = new GregorianCalendar(companyTimeZone); 
companyWorkStart.setTime(companyWorkStartHour); 

Calendar companyWorkEnd = new GregorianCalendar(companyTimeZone); 
companyWorkEnd.setTime(companyWorkEndHour); 

Calendar user = new GregorianCalendar(userTimeZone); 
user.setTime(userTime); 

if(user.compareTo(companyWorkStart)>=0 && user.compareTo(companyWorkEnd)<=0) { 
    ... 
} 
Powiązane problemy