php 根据营业时间确定业务是否开放/关闭

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14904864/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 08:10:38  来源:igfitidea点击:

Determine If Business Is Open/Closed Based On Business Hours

phpdatedatetimestrtotime

提问by Stephen

My code works fine if the times are AM to PM (Ex: 11 AM - 10 PM), but if the locations hours of operation are AM to AM (Ex: 9 AM - 1 AM) it breaks. Here is my code:

如果时间是上午到下午(例如:上午 11 点 - 晚上 10 点),我的代码可以正常工作,但是如果地点的营业时间是上午到上午(例如:上午 9 点 - 凌晨 1 点),它就会中断。这是我的代码:

$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('l g: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
}

回答by cryptic ツ

You would first need to create an array which will hold your days of the week, and their respective close/open time range(s).

您首先需要创建一个数组,该数组将保存您一周中的几天,以及它们各自的收盘/开盘时间范围。

/**
 * 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']
];

You then loop over the current day's time range(s) and check to see if the current time or supplied timestamp is within a range. You do this by using the DateTimeclass to generate a DateTimeobject for each time range's start/end time.

然后您遍历当天的时间范围并检查当前时间或提供的时间戳是否在一个范围内。为此,您可以使用DateTime类为每个时间范围的开始/结束时间生成一个DateTime对象。

The below will do this and allow you to specify a timestamp in case you are wanting to check a supplied timestamp instead of the current time.

下面将执行此操作并允许您指定时间戳,以防您想要检查提供的时间戳而不是当前时间。

// 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";

See DEMOof above

见上面的DEMO

回答by sdforet

Modified from the accepted answer for use on a AWS Debian Server (located on the west coast) where our store hours are actually EST... also dropped into a PHP function.

修改为在 AWS Debian 服务器(位于西海岸)上使用的公认答案,其中我们的商店营业时间实际上是美国东部标准时间……也放入了 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;
}

回答by Daniel P

You should regroup all opening hours in a array since the openings hours of yesterday could be of influence if you stay opened after midnight. Also having the possibility to have several opening hours per day might be handy.

您应该将所有开放时间重新组合成一个数组,因为如果您在午夜之后保持开放,昨天的开放时间可能会产生影响。每天有几个开放时间的可能性也很方便。

<?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";
}

?>

On the other hand if you only want to resolve the problem with time like 9am - 5amyou should check if $from > $toand add 1 day to $toif necessary.

另一方面,如果您只想随时间解决问题,例如9am - 5am您应该检查是否$from > $to$to在必要时添加 1 天。

回答by Xandor

A bit late but I have a solution for others, if the one's here don't quite fit their needs. I do like the solution of having multiple time sets for days that close after midnight but then this would add extra data handling to display the hours. You would first have to check if there are multiple time sets available then confirm that they are connected (no time in between).

有点晚了,但我有其他人的解决方案,如果这里的人不太适合他们的需求。我确实喜欢在午夜后关闭的几天内设置多个时间的解决方案,但这会增加额外的数据处理以显示小时数。您首先必须检查是否有多个可用的时间集,然后确认它们已连接(中间没有时间)。

My solution was instead to write a function that you pass the opening time, closing time, and time-in-question and it will return true for open and false for closed:

我的解决方案是编写一个函数,通过打开时间、关闭时间和问题时间,它将返回 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;
}

回答by Dakila Lozano

Here is my version since the 12hr time format does not work for me. Note that $pancits[] came from my database

这是我的版本,因为 12 小时时间格式对我不起作用。请注意 $pancits[] 来自我的数据库

$status = 'Closed';
// get current time object
$timestamp = time();
// $currentTime = (new DateTime())->setTimestamp($timestamp);
$currentTime = date('H:i');

$startTime = date('H:i', strtotime($pancits['p_oTime']));
$endTime   = date('H:i', strtotime($pancits['p_cTime']));

if (($startTime <= $currentTime) && ($currentTime <= $endTime)) {
    $status = 'Open';
    //echo $status;
}

echo "<b>Currently $status</b>";

echo '
    <p><b>Time Open: </b>'.date('h:ia', strtotime($pancits['p_oTime'])).'</p>
    <p><b>Time Close: </b>'.date('h:ia', strtotime($pancits['p_cTime'])).'</p>
';

回答by FtDRbwLXw6

I would suggest making use of PHP's DateTimeclass. It was developed to solve all these problems by giving a simple interface for hard to accomplish tasks like this.

我建议使用 PHP 的DateTime类。它的开发旨在通过为此类难以完成的任务提供简单的界面来解决所有这些问题。

回答by RA MEDIA

Maybe this? I found it hereand tweaked it a bit.

也许这个?我在这里找到它并稍微调整了一下。

    <?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("Y-m-d H:i") < date("Y-m-d H:i", strtotime('tomorrow +'.intval($closing_hours[$today]).' hours')))) 
    ) ||
    date("H:i") < $closing_hours[$today] && 
    ((date("Y-m-d H:i") < date("Y-m-d 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];
    }
    ?>

回答by Marty Demichele

I tried this code for a day several different ways and found this to be a solution for me. Posting it in case it might help others. It is important to convert the time from AM/PM format back to UNIX time.

我以几种不同的方式尝试了这段代码一天,发现这对我来说是一个解决方案。发布它以防它可能会帮助其他人。将时间从 AM/PM 格式转换回 UNIX 时间非常重要。

I use times pulled from a database so you would have to define $startTimeand $endTime.

我使用从数据库中提取的时间,因此您必须定义$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>";