2013-06-17 23 views
5

Mam system, który akceptuje przesyłanie przez użytkownika, a po otrzymaniu zgłoszenia system przejdzie przez wszystkie szczeliny czasowe, aby znaleźć odpowiednią szczelinę czasową. Problem polega na tym, że musi być w stanie sprawdzić przed czasem zakończenia &, jeśli czas zakończenia upływa do następnego dnia.Sprawdź, czy aktualny czas jest między dwoma czasami, z możliwością docierania dni

Weź następujący przykład: Godzina rozpoczęcia zaczyna się o 22:30 w bieżącym dniu, a kończy o godzinie 16:00 następnego dnia. Jeśli bieżący czas przypada między 22:30 a 23:59:59, zgłoszenie zostanie przypisane do tej szczeliny czasowej. Jeśli jednak bieżący czas przypada między godziną 12:00 a 16:00, pominie to okienko czasowe.

To, co mam tak daleko:

function check_time($from, $to, $time) { 
    $time = strtotime($time); 
    $from = strtotime($from); 
    $to_ = strtotime($to); 
    $to = $to_ <= $from ? strtotime($to . " tomorrow") : $to_; 
    return ($time >= $from && $time <= $to); 
} 

$timeslots = array(
    array("16:00:00", "22:30:00"), 
    array("22:30:00", "16:00:00") 
); 
foreach ($timeslots as $slot) { 
    if (check_time($slot[0], $slot[1], date("H:i:s"))) 
     { 
      echo "true\n"; 
     } 
    else 
     { 
      echo "false\n";  
     } 
} 

Jeśli bieżąca godzina 23:00:00, to wynik byłby

false 
true 

Ale jeśli obecny czas jest 12: 00:00 następnie wynik byłby następujący:

false 
false 

mimo że technicznie występuje między tymi dwoma czasami.

Wiem, że ma to związek z tym, że jeśli jest to nowy dzień, to wynik strtotime dla $from będzie późniejszy w tym dniu. Więc zamiast sprawdzać wczoraj o 22:30, sprawdza się dziś wieczorem o 22:30.

Moim problemem jest to, że nie mogę wymyślić sposobu, aby zmienić czas na $from na dzień wcześniej, podobnie jak wymuszam czas $to na następny dzień.

+0

Jeśli daty są ważne, to dlaczego nie dodać go do swoich czasów? –

+0

Godziny są dynamiczne. Czasy są przechowywane w bazie danych i mogą być zmienione według uznania administratora. Używamy go do dzielenia zgłoszeń, aby osoby dokonujące przeglądu zgłoszeń miały równe obciążenie pracą. –

Odpowiedz

7

Jest to znacznie łatwiejsze niż się spodziewasz.Załóżmy, że masz trzy razy, t1,i tn, które reprezentują odpowiednio od, do i użytkownika. Traktować te czasy jak sześciu liczb dwucyfrowych (od 000000 do 235959) i sprawdzić:

  • Jeśli t1 i t2 obecne są na tej samej stronie granicy północy
    • Sprawdź, czy tn leży między t1 i t2
  • Else
    • Sprawdź, czy tn nie leży między t2 i t1

kod i testy:

function check_time($t1, $t2, $tn) { 
    $t1 = +str_replace(":", "", $t1); 
    $t2 = +str_replace(":", "", $t2); 
    $tn = +str_replace(":", "", $tn); 
    if ($t2 >= $t1) { 
     return $t1 <= $tn && $tn < $t2; 
    } else { 
     return ! ($t2 <= $tn && $tn < $t1); 
    } 
} 
$tests = array(
    array("16:00:00", "22:30:00", "15:00:00"), 
    array("16:00:00", "22:30:00", "16:00:00"), 
    array("16:00:00", "22:30:00", "22:29:59"), 
    array("16:00:00", "22:30:00", "22:30:00"), 
    array("16:00:00", "22:30:00", "23:59:59"), 
    array("22:30:00", "16:00:00", "22:29:59"), 
    array("22:30:00", "16:00:00", "22:30:00"), 
    array("22:30:00", "16:00:00", "15:59:59"), 
    array("22:30:00", "16:00:00", "16:00:00"), 
    array("22:30:00", "16:00:00", "17:00:00") 
); 
foreach($tests as $test) { 
    list($t1, $t2, $t0) = $test; 
    echo "$t1 - $t2 contains $t0: " . (check_time($t1, $t2, $t0) ? "yes" : "no") . "\n"; 
} 
// OUTPUT 
// 
// 16:00:00 - 22:30:00 contains 15:00:00: no 
// 16:00:00 - 22:30:00 contains 16:00:00: yes 
// 16:00:00 - 22:30:00 contains 22:29:59: yes 
// 16:00:00 - 22:30:00 contains 22:30:00: no 
// 16:00:00 - 22:30:00 contains 23:59:59: no 
// 22:30:00 - 16:00:00 contains 22:29:59: no 
// 22:30:00 - 16:00:00 contains 22:30:00: yes 
// 22:30:00 - 16:00:00 contains 15:59:59: yes 
// 22:30:00 - 16:00:00 contains 16:00:00: no 
// 22:30:00 - 16:00:00 contains 17:00:00: no 
+0

+1 za oryginalność (NIE) :) To jest coś, co powiedziałem ... – CodeAngry

+1

Bardzo doceniane, właśnie tego szukałem. Nie myślałem nawet o zamianie czasów na liczby całkowite i porównywaniu ich jako normalnych liczb. Chyba powinienem zasnąć do północy, nie martwiąc się o sprawdzenie, czy jest północ. –

2
function check_time($time, $threshold){ 
    $times = array(&$time, &$threshold); 
    foreach($times as &$ts){ 
     if(!preg_match('~^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$~', $ts)){ 
      return false; 
     } 
     $ts = intval(preg_replace('~[^0-9]+~', null, $ts)); 
    } 
    return ($time >= $threshold) ? 2 : 1; 
} 

var_dump(check_time(date("H:i:s"), '12:00:00')); 

Oszukałem! Przyjrzyjmy się logice:

  • Dowolny czas można przekonwertować na liczbę całkowitą, jeśli usuniemy interpunkcję.
  • Usunąłem interpunkcję z $time, którą chcesz przetestować i uczyniłem ją liczbą całkowitą.
  • Zrobiłem to samo dla $threshold, która jest datą, która łamie spacje w slotach. Ta funkcja tylko sprawdza, czy liczba całkowita $time jest przed lub po wartości $threshold.
  • Nie obchodzi nic o datach, jutro, względności czasu i tym podobnych.

Jeśli to zawiedzie (złe wejście) to returns false. Jeśli to się powiedziezwraca liczbę całkowitą: - jeśli przed próg - jeśli po próg

Nadzieję, że pasuje do Twoich potrzeb.