2011-11-26 17 views
9

Jak radzić sobie z czasami i po północy w PHP/MySQL?Radzenie sobie z czasami i po północy

Należy użyć minuta lub użyć pola typu ?

Rozważmy zapytań SQL poniżej:

SELECT * FROM opening_hours 
     WHERE week_day = WEEKDAY(NOW()) + 1 
       AND open_hour =< date_format(now(),'%H:%i') 
       AND close_hour >= date_format(now(),'%H:%i') 

open_hour/close_hour pola są TIME typ pola.

Załóżmy, że open_time ma wartość "18:00", czas zamknięcia to "02:00", aktualny czas to "22:41". Mamy oddzielny rekord DB dla czasu zamknięcia (bo jest po północy), ale nigdy nie otrzymamy go w wyniku, ponieważ czas zamknięcia "02:00" NIE jest większy niż aktualny czas, "22:41".

Również jeśli bieżący czas to "01:00", otrzymamy NEXT wartości dnia, ponieważ dzień tygodnia nie pasuje.

Jakie jest rozwiązanie?

Czy wolisz przechowywać te wartości w INT (minuty), więc php może przetwarzać te wartości bezpośrednio, bez jakiejkolwiek konwersji?

Na przykład ...

Aktualny czas:

// w = Day of the week, H = 24-hour format, i = Minutes 
$timearr = explode(':',date("w:H:i")); 
$currenttime = ($timearr[0]) * 1440 + $timearr[1] * 60 + $timearr[2] 

W bazie danych zapisane open/close wartości czasu w minutach.

Załóżmy teraz, że aktualny czas to "Słońce, 01:00" (pierwszy dzień tygodnia), wykonując powyższą okładkę, ta wartość wynosi 60; a czasy otwarcia/zamknięcia ostatniego dnia tygodnia (soboty) są ustawione na "17:00" i "02:00" (co jest faktycznie niedzielą), przechowywane w DB jako 9660 i 10200 (sobota, 26:00) . W tym przypadku powyższe zapytanie nie znajdzie potrzebnego rekordu (Sat, 17:00, 02:00), ponieważ prawdopodobnie nie mamy żadnego okresu open_time krótszego niż "02:00" (120). Aby rozwiązać ten problem, konwertujemy "Słońce, 01:00" na "Sob, 25:00", dodając 7 * 1440 (cały tydzień) do $ currenttime, co da 10140. Następnie zapytanie DB wygląda następująco:

SELECT open_time,clos_time FROM open_hours 
    WHERE (open_time <= $currenttime 
     AND close_time >= $currenttime) 
     OR (open_time <= $currenttime +10080 
     AND close_time >= $currenttime + 10080); 

A co jest rozwiązaniem alternatywnym i schludniejszym?

+0

Może przechowywać datę wraz z czasem? po północy czas staje się czasem jutrzejszym. Użyj również formatu DATETIME, a nie INT lub innych. –

+0

Nie Nie mogę użyć DATETIME, ponieważ nie używam Date. Kupuj codziennie, nie chcę dodawać daty przez cały rok! –

+0

http://stackoverflow.com/questions/8225684/how-to-find-out-if-store-open-lub-close-dealing-withh godzin –

Odpowiedz

1

Przechowywanie minut (int (4) bez znaku) jest drogą do zrobienia.
Jednak zamiast przechowywania tygodnia + opening_hour, zamykając godzinę (z przesunięciem),
należy przechowywać w chwili, ponieważ w poniedziałek 12am: -

Monday 18:00 = (1 - 1)*60 * 18 = 1080 
Tuesday 02:00 = (2 - 1)*60 * 24 + (2 * 60) = 1560 
... 
// please take note shop could have different operating hour for each day 

Tak, obecny czas jest wtorek 01:30, który jest: -

// mysql expression 
$expr = (weekday(current_timestamp)+1) * 1440 + (hour(current_timestamp)*60) + minute(current_timestamp) 

SQL: -

select ... 
from opening_hours 
where 
open_time >= $expr and 
close_time <= $expr; 
+0

Nie rozumiem tej części: '(1 - 1)' i '(2 - 1)'? co to jest? –

+0

1 = dzień roboczy rozpoczyna się od poniedziałku, w poniedziałek = 0, wtorku = 1. .. niedziela = 7 (to znaczy początek tygodnia od poniedziałku) – ajreal

+0

Wygląda jak dodatkowa warstwa o niezbyt złożonej złożoności, jeśli mnie pytasz. Chciałbym zapisać czas w 24-godzinnym zegarze w postaci ciągu, zanim to zrobię (np. 0800, 1200, 2140 itd.). Porównania wciąż działają i możesz łatwo spojrzeć na liczby i zrozumieć, co się dzieje. – Zoidberg

1
SELECT open_time,close_time FROM open_hours 
    WHERE 
     (open_time <= close_time AND 
     open_time <= $currenttime AND 
     close_time >= $currenttime) 
     OR 
     (open_time >= close_time AND 
     ($currenttime <= close_time OR 
     $currenttime >= open_time)) 

Więc co ja robie tu jest, jeśli open_time jest większa niż close_time, to musi rozciągać się po północy, w takim przypadku mogę sprawdzić, aktualny licznik jest większy niż czas otwarty, lub mniej niż zżyci więc zapewniona jest wpaść w naszym przedziale czasowym

czas otwarcia ------ Midnight ----- zżyci

Jeśli czas otwarcia wynosi mniej niż zżyci, to wiemy połowie nocy nie spada pomiędzy. W rezultacie możemy po prostu sprawdzić, jak zwykle.

+0

Aha, więc wolisz przechowywać te wartości w INT (minuty) w tej sytuacji? –

+0

Jest to, co chcesz. Wiem, że data nie ma znaczenia w tej sytuacji, więc myślę, że datetime nie byłoby drogą do zrobienia. Myślę, że istnieje typ czasu w MySql http://dev.mysql.com/doc/refman/5.0/en/time.html, który byłby idealny. – Zoidberg

0

nie wiem, co próbujesz zrobić, ale nam Użycie znaczników czasu unix zawsze było właściwą odpowiedzią w mojej opcji. jest łatwiejsza do obliczenia i zawsze jest właściwa niezależnie od stref czasowych.

Może powinieneś zajrzeć do tego

+0

Datownik nadal przechowuje informacje o dacie, które nie są wymagane w tym przypadku, ponieważ czas zamknięcia i otwarcia pojawiałby się codziennie. – Zoidberg

+0

tak, ale możesz wydobyć właściwy czas: data echa ("g: i a", $ timestamp); –

Powiązane problemy