Мой код работает отлично, если время AM до PM (например: 11:00 – 10:00), но если часы работы работают с AM до AM (Ex: 9 AM – 1 AM), он прерывается. Вот мой код:
$datedivide = explode(" - ", $day['hours']); //$day['hours'] Example 11:00 AM - 10:00 PM $from = ''.$day['days'].' '.$datedivide[0].''; $to = ''.$day['days'].' '.$datedivide[1].''; $date = date('lg:i A'); $date = is_int($date) ? $date : strtotime($date); $from = is_int($from) ? $from : strtotime($from); $to = is_int($to) ? $to : strtotime($to); if (($date > $from) && ($date < $to) && ($dateh != 'Closed')) { ?> <script type="text/javascript"> $(document).ready(function(){ $('.entry-title-container').append('<div class="column two"><h2 style="color:green;text-align: left;margin: 0;">OPEN<br /><span style="color:#222;font-size:12px;display: block;">Closes at <?php echo $datedivide[1]; ?></span></h2></div><br clear="all" />'); }); </script> <?php }
Сначала вам нужно создать массив, в котором будут храниться дни недели, и их соответствующие диапазоны закрытия / открытия.
/** * I setup the hours for each day if they carry-over) * everyday is open from 09:00 AM - 12:00 AM * Sun/Sat open extra from 12:00 AM - 01:00 AM */ $storeSchedule = [ 'Sun' => ['12:00 AM' => '01:00 AM', '09:00 AM' => '12:00 AM'], 'Mon' => ['09:00 AM' => '12:00 AM'], 'Tue' => ['09:00 AM' => '12:00 AM'], 'Wed' => ['09:00 AM' => '12:00 AM'], 'Thu' => ['09:00 AM' => '12:00 AM'], 'Fri' => ['09:00 AM' => '12:00 AM'], 'Sat' => ['12:00 AM' => '01:00 AM', '09:00 AM' => '12:00 AM'] ];
Затем вы перебираете временной диапазон (ы) текущего дня и проверяете, находится ли текущее время или поставленная метка времени в пределах диапазона. Вы делаете это, используя класс DateTime для создания объекта DateTime для начала / окончания времени каждого временного диапазона.
Ниже мы сделаем это и позволим вам указать временную метку, если вы хотите проверить поставленную метку времени вместо текущего времени.
// current or user supplied UNIX timestamp $timestamp = time(); // default status $status = 'closed'; // get current time object $currentTime = (new DateTime())->setTimestamp($timestamp); // loop through time ranges for current day foreach ($storeSchedule[date('D', $timestamp)] as $startTime => $endTime) { // create time objects from start/end times $startTime = DateTime::createFromFormat('h:i A', $startTime); $endTime = DateTime::createFromFormat('h:i A', $endTime); // check if current time is within a range if (($startTime < $currentTime) && ($currentTime < $endTime)) { $status = 'open'; break; } } echo "We are currently: $status";
См. DEMO выше
Вы должны перегруппировать все часы работы в массиве, поскольку вчерашние часы открытия могут повлиять, если вы останетесь открыты после полуночи. Также возможно иметь возможность иметь несколько часов работы в день.
<?php $times = array( 'mon' => '9:00 AM - 12:00 AM', 'tue' => '9:00 AM - 12:00 AM', 'wed' => '9:00 AM - 12:00 AM', 'thu' => '9:00 AM - 12:00 AM', 'fri' => '9:00 AM - 1:00 AM', 'sat' => '9:00 AM - 1:00 PM, 2:00 PM - 1:00 AM', 'sun' => 'closed' ); function compileHours($times, $timestamp) { $times = $times[strtolower(date('D',$timestamp))]; if(!strpos($times, '-')) return array(); $hours = explode(",", $times); $hours = array_map('explode', array_pad(array(),count($hours),'-'), $hours); $hours = array_map('array_map', array_pad(array(),count($hours),'strtotime'), $hours, array_pad(array(),count($hours),array_pad(array(),2,$timestamp))); end($hours); if ($hours[key($hours)][0] > $hours[key($hours)][1]) $hours[key($hours)][1] = strtotime('+1 day', $hours[key($hours)][1]); return $hours; } function isOpen($now, $times) { $open = 0; // time until closing in seconds or 0 if closed // merge opening hours of today and the day before $hours = array_merge(compileHours($times, strtotime('yesterday',$now)),compileHours($times, $now)); foreach ($hours as $h) { if ($now >= $h[0] and $now < $h[1]) { $open = $h[1] - $now; return $open; } } return $open; } $now = strtotime('7:59pm'); $open = isOpen($now, $times); if ($open == 0) { echo "Is closed"; } else { echo "Is open. Will close in ".ceil($open/60)." minutes"; } ?>
С другой стороны, если вы хотите только решить проблему со временем, например 9am - 5am
вы должны проверить, стоит ли $from > $to
и добавить 1 день до $to
если необходимо.
Изменен из принятого ответа для использования на сервере AWS Debian (расположенном на западном побережье), где наши часы магазина на самом деле EST … также попадают в функцию PHP.
/* * decide based upon current EST if the store is open * * @return bool */ function storeIsOpen() { $status = FALSE; $storeSchedule = [ 'Mon' => ['08:00 AM' => '05:00 PM'], 'Tue' => ['08:00 AM' => '05:00 PM'], 'Wed' => ['08:00 AM' => '05:00 PM'], 'Thu' => ['08:00 AM' => '05:00 PM'], 'Fri' => ['08:00 AM' => '05:00 PM'] ]; //get current East Coast US time $timeObject = new DateTime('America/New_York'); $timestamp = $timeObject->getTimeStamp(); $currentTime = $timeObject->setTimestamp($timestamp)->format('H:i A'); // loop through time ranges for current day foreach ($storeSchedule[date('D', $timestamp)] as $startTime => $endTime) { // create time objects from start/end times and format as string (24hr AM/PM) $startTime = DateTime::createFromFormat('h:i A', $startTime)->format('H:i A'); $endTime = DateTime::createFromFormat('h:i A', $endTime)->format('H:i A'); // check if current time is within the range if (($startTime < $currentTime) && ($currentTime < $endTime)) { $status = TRUE; break; } } return $status; }
Я бы предложил использовать PHP-класс DateTime
. Он был разработан для решения всех этих проблем, предоставляя простой интерфейс для выполнения таких задач.
Может быть, это? Я нашел его здесь и немного изменил его.
<?php date_default_timezone_set('Europe/Stockholm'); // timezone $today = date(N); // today ex. 6 //Opening hours $opening_hours[1] = "12:00"; $closing_hours[1] = "00:00"; $opening_hours[2] = "12:00"; $closing_hours[2] = "00:00"; $opening_hours[3] = "12:00"; $closing_hours[3] = "00:00"; $opening_hours[4] = "12:00"; $closing_hours[4] = "02:00"; $opening_hours[5] = "12:00"; $closing_hours[5] = "04:00"; $opening_hours[6] = "13:00"; $closing_hours[6] = "04:00"; $opening_hours[7] = "13:00"; $closing_hours[7] = "00:00"; // correction for opening hours after midnight. if(intval($closing_hours[$today - 1]) > 0) $today = date(N,strtotime("-".intval($closing_hours[$today - 1])." hours")); // now check if the current time is after openingstime AND smaller than closing hours of tomorrow if ( (date("H:i") > $opening_hours[$today] && ((date("Ymd H:i") < date("Ymd H:i", strtotime('tomorrow +'.intval($closing_hours[$today]).' hours')))) ) || date("H:i") < $closing_hours[$today] && ((date("Ymd H:i") < date("Ymd H:i", strtotime('today +'.intval($opening_hours[$today]).' hours')))) ) { $label = "label-success"; $label_text = "OPEN"; $label_time = $closing_hours[$today]; } else { $label = "label-danger"; $label_text = "GESLOTEN"; $label_time = $opening_hours[$today]; } ?>
Я пробовал этот код в течение нескольких дней несколькими способами и нашел, что это решение для меня. Проводка его в случае, если она может помочь другим. Важно преобразовать время из формата AM / PM обратно в UNIX.
Я использую время, извлеченное из базы данных, поэтому вам нужно будет определить $startTime
и $endTime
.
// define each days time like so $monsta = "07:00 AM"; $monend = "05:00 PM"; $storeSchedule = [ 'Mon' => ["$monsta" => "$monend"], 'Tue' => ["$tuessta" => "$tuesend"], 'Wed' => ["$wedssta" => "$wedsend"], 'Thu' => ["$thurssta" => "$thursend"], 'Fri' => ["$frista" => "$friend"], 'Sat' => ["$satsta" => "$satend"], 'Sun' => ["$sunsta" => "$sunend"] ]; // default time zone $timestamp = time() - 18000; // default status $status = 'Closed'; // loop through time ranges for current day foreach ($storeSchedule[date('D', $timestamp)] as $startTime => $endTime) { // create time objects from start/end times $startTime = strtotime($startTime); $endTime = strtotime($endTime); // check if current time is within a range if ($startTime <= $timestamp && $timestamp <= $endTime ) { $status = 'Open'; } } echo '<p><b>Today\'s Hours</b><br />'.$days[$d].'<br />'; echo "<b>We are currently: $status </b></p>";
Немного поздно, но у меня есть решение для других, если они здесь не совсем соответствуют их потребностям. Мне нравится решение иметь несколько наборов времени для дней, которые закрываются после полуночи, но затем это добавит дополнительную обработку данных для отображения часов. Сначала вам нужно будет проверить наличие нескольких наборов времени, а затем подтвердить, что они подключены (время между ними отсутствует).
Моим решением было написать функцию, в которой вы передаете время открытия, время закрытия и время в вопросе, и оно вернет true для open и false для закрытых:
function is_open($open, $close, $query_time){ $open = new DateTime($open); $close = new DateTime($close); $query_time = new DateTime($query_time); $is_open = false; //Determine if open time is before close time in a 24 hour period if($open < $close){ //If so, if the query time is between open and closed, it is open if($query_time > $open){ if($query_time < $close){ $is_open = true; } } } elseif($open > $close){ $is_open = true; //If not, if the query time is between close and open, it is closed if($query_time < $open){ if($query_time > $close){ $is_open = false; } } } return $is_open; }