【问题标题】:PHP Decrease count between datesPHP减少日期之间的计数
【发布时间】:2012-04-03 08:56:11
【问题描述】:

我目前正在努力完成一项基本任务。我有一个开始日期、一个结束日期和一个计数。我需要计算第三个参数(计数)在两个日期之间每小时应该减少多少次:就像这样,countOffers("2012-03-27 11:00:00", "2012-04-08 19:00:00", 200) 每小时。

那一点,我想我们已经涵盖了。现在问题来了。

我们只希望在我们的网站打开时进行计数。这些时间存储在一个数组中,0 索引是打开的,1 是关闭的。此外,日期会动态更新为now

Array
(
    [mon] => Array
        (
            [0] => 2012-04-03 9:00
            [1] => 2012-04-03 21:30
        )

    [tue] => Array
        (
            [0] => 2012-04-03 9:00
            [1] => 2012-04-03 21:30
        )

    [wed] => Array
        (
            [0] => 2012-04-03 9:00
            [1] => 2012-04-03 21:30
        )

    [thu] => Array
        (
            [0] => 2012-04-03 9:00
            [1] => 2012-04-03 21.30
        )

    [fri] => Array
        (
            [0] => 2012-04-03 9:00
            [1] => 2012-04-03 19:00
        )

    [sat] => Array
        (
            [0] => 2012-04-03 9:00
            [1] => 2012-04-03 18:00
        )

    [sun] => Array
        (
            [0] => 2012-04-03 10:30
            [1] => 2012-04-03 19:00
        )

)

因此,当我们处于营业时间之间时,柜台每小时都会减少一次。但是,当我们关闭时,我们需要计算计数器到今天的关闭时间。

openTimes 有一个名为areWeOpen 的变量,我们可以使用它来检查我们当前是打开还是关闭。我们有一些代码,但它似乎并不总是有效:

function countOffers($start, $end, $deals) {
    global $openTimes;

    if(strtotime($end) < time()) return 1;

    define('ONEHOUR', 1);

    $totalDays   = unixtojd(strtotime($end)) - unixtojd(strtotime($start));
    $daysBefore  = unixtojd(time()) - unixtojd(strtotime($start));
    $daysAfter   = unixtojd(strtotime($end)) - unixtojd(time());
    $startDay    = strtolower(date("D", strtotime(date("Y-m-d", strtotime($start)))));
    $totalHours  = 0;
    $hoursBefore = 0;

    /* TOTAL HOURS */
    for($i = 0; $i <= $totalDays; $i++) {
        $dayName = strtolower(date("D", strtotime(date("Y-m-d", strtotime($start)) . " +$i days")));
        $day = $openTimes->openDays[$dayName];
        if($i === 0) {
            $startHour = explode(" ", $start);
            $startHour = str_replace(array(":","3"), array(".","5"), $startHour[1]);
            $endHour = explode(" ", $day[1]);
            $endHour = str_replace(array(":","3"), array(".","5"), $endHour[1]);
            $totalHours += $endHour - $startHour;
        } else {
            $tempHour = (strtotime($day[1]) - strtotime($day[0])) / 3600;
            $totalHours += (strtotime($day[1]) - strtotime($day[0])) / 3600;
        }
    }
    $perHour = round($deals / $totalHours, 1);

    $today = 0;
    if($openTimes->areWeOpen === FALSE && $openTimes->morning === FALSE) {
        /* HOURS UP TO TODAY */
        for($i = 0; $i < $daysBefore; $i++) {
            $day = $openTimes->openDays[strtolower(date("D", strtotime(date("Y-m-d", strtotime($start)) . " +$i days")))];
            $hoursBefore += (strtotime($day[1]) - strtotime($day[0])) / 3600; 
        }
    } elseif (strtotime($start) <= time()) {
        /* HOURS UP TO YESTERDAY */
        for($i = 0; $i < ($daysBefore-1); $i++) {
            $day = $openTimes->openDays[strtolower(date("D", strtotime(date("Y-m-d", strtotime($start)) . " +$i days")))];
            $hoursBefore += (strtotime($day[1]) - strtotime($day[0])) / 3600; 
        }

        if(strstr($start, date("Y-m-d", time()))) {
            $today = ceil((time() - strtotime($start)) / 3600) - ONEHOUR;
        } else {
            $today = ceil((time() - strtotime($openTimes->openDays[strtolower(date("D", time()))][0])) / 3600) - ONEHOUR;
        }
    }
    $alreadyGone = $hoursBefore*$perHour;

    $dealsLeft = $deals - (($hoursBefore*$perHour) + ($today*$perHour));
    if($dealsLeft < 0.5) $dealsLeft = 1;

    return round($dealsLeft);
}

它会正确计数,但是当我们关闭时它似乎很挣扎,它会继续减少。我知道必须有更好的方法来做到这一点,我只是想不通。我想我已经把脑子里的问题复杂化了。

*编辑:* 好的,这是我想要实现的目标的分解:

在开放时间(以数组形式提供)我需要减少一天中的值x 的次数。如果我们关闭了,那么我们只想减小该值直到最后关闭时间。

我们得到一个开始日期、结束日期和计数器的开始编号。在每天上午 9 点到晚上 9 点之间,该值可能会下降。如果已经过了那个时间,或者我们目前关门了,我们只想减少到最后一个关门时间(可能是昨天)。

【问题讨论】:

  • 题外话,但我真的很感兴趣为什么一个网站会有开放时间。
  • 因为没有工作人员接听这些电话?我们不在线销售任何东西。我们的网站就像一本在线宣传册。
  • @James,您可能会喜欢...在您的网站中轻松声明在某些特定时间不打电话...?
  • 这不是我遇到的问题。我的营业时间很好,已经有一段时间了。我要做的就是在我们营业时减少柜台,同时考虑到每天的营业时间(每天都不同)。
  • 这个过程的实际应用是什么?做一些背景更新?向用户显示一些警报?所需的输出等,将比代码更有帮助

标签: php date datediff


【解决方案1】:

这不是最漂亮或最有效的代码,但我认为它可以满足您的要求。

<?php
/* test data
$openTimes->openDays = array(
'mon' => array('2012-03-27 09:00', '2012-03-27 21:30'),
'tue' => array('2012-03-27 09:00', '2012-03-27 21:30'),
'wed' => array('2012-03-27 09:00', '2012-03-27 21:30'),
'thu' => array('2012-03-27 09:00', '2012-03-27 21:30'),
'fri' => array('2012-03-27 09:00', '2012-03-27 19:00'),
'sat' => array('2012-03-27 09:00', '2012-03-27 18:00'),
'sun' => array('2012-03-27 10:30', '2012-03-27 19:00'),
);
*/

function countOffers($start, $end, $deals, $now='') {
    $start = new DateTime($start);
    $end = new DateTime($end);
    $now = new DateTime($now);
    if ($now <= $start) {
        return $deals;
    }
    if ($now >= $end) {
        return 0;
    }
    $totalHours = openTimeBetween($start, $end) / 60 / 60;
    $hoursRemaining = openTimeBetween($now, $end) / 60 / 60;
    $perHour = $deals / $totalHours;
    return (int)round($hoursRemaining * $perHour);
}

function openTimeBetween($start, $end) {
    $totalTime = 0;
    $today = new DateTime($start->format('Y-m-d H:i:s'));
    while ($today <= $end) {
        $totalTime += openTimeRemaining($today, $start, $end);
        // set time to midnight the next day
        $today->setTime(0, 0, 0);
        $today->modify('+1 day');
    }
    return $totalTime;
}

function openTimeRemaining($current, $minTime, $maxTime) {
    global $openTimes;
    // get the open/close times
    $day = strtolower($current->format('D'));
    list($open, $close) = $openTimes->openDays[$day];
    $open = new DateTime($open);
    $close = new DateTime($close);
    // set the date to be the same as $current
    $open->setDate($current->format('Y'), $current->format('m'), $current->format('d'));
    $close->setDate($current->format('Y'), $current->format('m'), $current->format('d'));

    // if it's past closing time or past the maximum time
    if ($current > $close || $current > $maxTime) {
        return 0;
    }
    // if it's the first day, count from $minTime or $current, whichever is later
    else if ($current->format('Y-m-d') === $minTime->format('Y-m-d')) {
        $diff = max($minTime, $current, $open)->diff($close);
    }
    // if it's the last day, count to $maxTime or $close, whichever is earlier
    else if ($current->format('Y-m-d') === $maxTime->format('Y-m-d')) {
        $diff = max($current, $open)->diff(min($maxTime, $close));
    }
    // otherwise count the total open time
    else {
        $diff = $open->diff($close);
    }
    return $diff->h * 60 * 60 + $diff->i * 60 + $diff->s;
}

为了测试,您可以调用countOffers(),并使用第四个参数字符串作为当前时间。

$start = '2012-03-27 11:00:00';
$end = '2012-04-08 19:00:00';
$offers = 200;
$now = '2012-04-04 17:00:00';
countOffers($start, $end, $offers, $now);

去掉多余的参数,默认为当前时间。

【讨论】:

  • 近在咫尺,我能感觉到。但是,如果现在是早上而且我们关门了,我无法让它回到昨天的关门时间。我要一把小提琴!不过谢谢!
  • 全部排序!非常感谢:3
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-17
  • 2013-03-09
  • 2018-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多