2012-12-15 12 views
12

Przechowuję godziny/daty w bazie danych przy użyciu znacznika czasu unix. Chcę wtedy pobrać wszystkie wystąpienia w określonym dniu, dlatego też muszę obliczyć znacznik czasu na początku dnia, aby wysłać zapytanie do bazy danych.Pobierz sygnaturę czasową na początek dnia

Zrobiłem podobną rzecz w php, przekazując mktime wartości dnia/miesiąca/roku z obiektu daty i ustawienie godziny i minuty na zero. Wydaje się, że nie ma podobnych funkcji w java/android (funkcje uzyskiwania określonych części daty są przestarzałe)

Czy ktoś może udzielić wskazówek na ten temat? Dzięki

Edit:

Ok więc zdałem sobie sprawę, że to może działać:

public static int startOfDay(Timestamp time) { 
     Calendar cal = dateToCalendar(new Date(time.getTime())); 
     cal.add(Calendar.HOUR_OF_DAY, -Calendar.HOUR_OF_DAY); 
     cal.add(Calendar.MINUTE, -Calendar.MINUTE); 
     cal.add(Calendar.SECOND, -Calendar.SECOND); 
     Log.i("Time", cal.getTime().toString());   
     return (int) cal.getTimeInMillis()/1000; 
} 

Jednak kiedy wpadłem to właśnie teraz mam:

Sob 15 grudnia 01:24:00 GMT 2012

Sekundy są prawidłowe, ale godzina i minuta są nieprawidłowe?

Odpowiedz

32

W przypadku czasu należy zawsze brać pod uwagę strefy czasowe. Znaczniki czasu bazy danych powinny być zawsze przechowywane w jednej strefie czasowej (np. UTC). Twoje obliczenia powinny następnie uwzględniać, że użytkownicy mogą znajdować się w różnych strefach czasowych i mogą zmieniać strefy czasowe.

Jeśli chcesz obliczyć początek dnia w strefie czasowej, którą użytkownik ustawił w swoim telefonie. Tworzenie instancji Calendar z:

Calendar cal = Calendar.getInstance(); 

Aby uzyskać instancji dla określonego zastosowania strefa czasu:

// use UTC time zone 
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 

Następnie ustaw początek dnia:

cal.setTime(time); // compute start of the day for the timestamp 
cal.set(Calendar.HOUR_OF_DAY, 0); 
cal.set(Calendar.MINUTE, 0); 
cal.set(Calendar.SECOND, 0); 
cal.set(Calendar.MILLISECOND, 0); 
6
public static int startOfDay(Timestamp time) { 
    Calendar cal = Calendar.getInstance(); 
    cal.setTimeInMillis(time.getTime()); 
    cal.set(Calendar.HOUR_OF_DAY, 0); //set hours to zero 
    cal.set(Calendar.MINUTE, 0); // set minutes to zero 
    cal.set(Calendar.SECOND, 0); //set seconds to zero 
    Log.i("Time", cal.getTime().toString());   
    return (int) cal.getTimeInMillis()/1000; 
} 
+0

Och, dzięki nie zdawałem sobie sprawy, że to działa tak. –

+0

jak nazwać tę metodę –

1

tl; dr

ZoneId z = ZoneId.of("America/Montreal"); 
long secondsSinceEpoch = ZonedDateTime.now(z).toLocalDate().asStartOfDay(z).toEpochSecond() ; 

Szczegóły

Przyjęty Answer by Tomik jest poprawny, ale nieaktualny. Uciążliwe stare starsze klasy daty i czasu zostały wyparte przez klasy java.time.

Zgodnie z tą odpowiedzią należy uwzględnić strefę czasową podczas rozpoczęcia dnia. Strefa czasowa ma kluczowe znaczenie przy ustalaniu daty. W danym momencie data zmienia się na całym świecie według strefy. Na przykład, kilka minut po północy w Paryżu Francja jest nowym dniem, a jednocześnie "wczoraj" w Montrealu Québec.

ZoneId z = ZoneId.of("America/Montreal"); 
ZonedDateTime zdt = ZonedDateTime.now(z); 

Pierwsze pierwszy moment dnia wymaga przechodzenia przez LocalDate. Klasa LocalDate reprezentuje wartość tylko dla daty bez pory dnia i bez strefy czasowej.

LocalDate today = zdt.toLocalDate(); 
ZonedDateTime zdtTodayStart = today.atStartOfDay(z); 

Pamiętaj, że zezwalamy java.czas określa początek dnia, a nie zakładanie i kodowanie na sztywno 00:00:00. Z powodu czasu letniego (DST) i innych anomalii, dzień może rozpocząć się w innym czasie, na przykład 01:00:00.

Podobno przez unix timestamp należy rozumieć liczbę pełnych sekund od pierwszej chwili 1970 roku w UTC. Klasa ZonedDateTime ma metodę podania tego numeru. Uwaga: może to oznaczać utratę danych, ponieważ ZonedDateTime może mieć ułamek sekundy z rozdzielczością nanosekund.

long secondsSinceEpoch = zdtTodayStart.toEpochSecond(); 

O java.time

Ramy java.time jest wbudowana w Java 8 i późniejszych. Klasy te zastępują kłopotliwe stare klasy czasu i daty, takie jak java.util.Date, .Calendar, .

Projekt Joda-Time, teraz w maintenance mode, zaleca migrację do java.time. Aby uzyskać więcej informacji, zobacz

. I wyszukaj Stack Overflow dla wielu przykładów i objaśnień.

Znaczna część funkcjonalności java.time powraca walcowy Java 6 & 7 w ThreeTen-Backport i ponadto dostosowany do Android w ThreeTenABP (patrz How to use…).

Projekt ThreeTen-Extra rozszerza java.time o dodatkowe klasy. Ten projekt jest poligonem wskazującym na możliwe przyszłe dodatki do java.time. Możesz znaleźć tutaj kilka użytecznych klas, takich jak Interval, YearWeek, YearQuarter i więcej.

3

Co sądzisz o tym prostym rozwiązaniu?

Long currentDayStart = timestamp - timestamp%86400000; 
Long currentDayEnd = timestamp+86399999; 

Zmiana stref czasowych dla sygnatury czasowej jest niepotrzebna. Więcej tutaj: https://stackoverflow.com/a/23062640

Powiązane problemy