用PHP计算工作时间差

用PHP计算工作时间差,php,Php,我想计算编码日期和完成日期之间的小时数。到目前为止,我可以计算两个日期时间之间的时间差,不包括周六和周日。我的问题是我需要排除午餐休息时间(上午12:00到下午1:00)和节假日 这是我的密码: <?php function business_hours($start, $end){ $startDate = new DateTime($start); $endDate = new DateTime($end); $periodInterval = new Dat

我想计算编码日期和完成日期之间的小时数。到目前为止,我可以计算两个日期时间之间的时间差,不包括周六和周日。我的问题是我需要排除午餐休息时间(上午12:00到下午1:00)和节假日

这是我的密码:

<?php
function business_hours($start, $end){

    $startDate = new DateTime($start);
    $endDate = new DateTime($end);
    $periodInterval = new DateInterval( "PT1H" );

    $period = new DatePeriod( $startDate, $periodInterval, $endDate );
    $count = 0;

    $holidays = [
      "Human Rights Day"      => new DateTime(date('Y') . '-03-21'),
      "Good Friday"           => new DateTime(date('Y') . '-03-30'),
      "Family Day"            => new DateTime(date('Y') . '-04-02'),
      "Freedom Day"           => new DateTime(date('Y') . '-04-27'),
      "Labour Day"            => new DateTime(date('Y') . '-05-01'),
      "Youth Day"             => new DateTime(date('Y') . '-06-16'),
      "National Women's Day"  => new DateTime(date('Y') . '-08-09'),
      "Heritage Day"          => new DateTime(date('Y') . '-09-24'),
      "Day of Reconciliation" => new DateTime(date('Y') . '-12-16'),
    ];

    foreach($period as $date){

    $startofday = clone $date;
    $startofday->setTime(8,00);

    $endofday = clone $date;
    $endofday->setTime(17,00);

        if($date > $startofday && $date <= $endofday && !in_array($date->format('l'), array('Sunday','Saturday'))){
            $count++;
        }

    }
    echo $count;
}

$start = '2020-02-14 08:00:00';
$end = '2020-02-17 08:00:00';

$go = business_hours($start,$end);

//output 9 hours
?>

每天尝试在循环中添加一些条件以跳过几个小时怎么样

($date->format('H') <= 12 || $date->format('H') > 13)
并检查每个日期循环是否在Holyday列表中

in_array($date->format('Y-m-d'), $holyDays)
您将获得休息时间过滤器和自定义休息日

function business_hours($start, $end,$holyDays = null){

    $startDate = new DateTime($start);
    $endDate = new DateTime($end);
    $periodInterval = new DateInterval( "PT1H" );

    $period = new DatePeriod( $startDate, $periodInterval, $endDate );
    $count = 0;



    foreach($period as $date){
        $startofday = clone $date;
        $startofday->setTime(8,00);
        $endofday = clone $date;
        $endofday->setTime(17,00);

        //just some var to use in conditional check
        $notHolyday = true;

        //now check the array of holyday and check if in range dates is same with holydays we have
        if($holyDays != null && is_array($holyDays) && in_array($date->format('Y-m-d'), $holyDays)){
            $notHolyday = false;
        }

        if($date > $startofday && $date <= $endofday && !in_array($date->format('l'), array('Sunday','Saturday')) && ($date->format('H') <= 12 || $date->format('H') > 13) && $notHolyday){
            $count++;

        }

    }
    echo $count;
}

$start = '2020-02-14 08:00:00';
$end = '2020-02-19 08:00:00';
$holyDays = array('2020-02-17','2020-02-18');
$count = business_hours($start,$end,$holyDays);

echo $count;
function business\u hours($start、$end、$holyDays=null){
$startDate=新日期时间($start);
$endDate=新日期时间($end);
$periodInterval=新日期间隔(“PT1H”);
$period=new DatePeriod($startDate,$periodInterval,$endDate);
$count=0;
foreach($期间为$日期){
$startofday=克隆$date;
$startofday->setTime(8,00);
$endofday=克隆$date;
$endofday->setTime(17,00);
//只是一些用于条件检查的变量
$notHolyday=正确;
//现在检查holyday数组,并检查范围内的日期是否与我们的holyday相同
如果($holyDays!=null&&is_数组($holyDays)&&in_数组($date->format('Y-m-d'),$holyDays)){
$notHolyday=假;
}
如果($date>$startofday&&$date格式('l')、数组('Sunday'、'Saturday'))和($date->format('H')格式('H')>13)和($noholyday){
$count++;
}
}
echo$count;
}
$start='2020-02-1408:00:00';
$end='2020-02-19 08:00:00';
$holyDays=阵列('2020-02-17'、'2020-02-18');
$count=营业时间($start、$end、$holyDays);
echo$count;

我希望这是您想要的

因为您使用的是静态/定义的午休时间,您可以使用以下逻辑:

  • 如果$startDate是工作日,且在12:00之前,则为午餐计算的开始日期;否则就是下一个工作日了
  • 如果$endDate是一个工作日,且在13:00之后,则这是午餐计算的结束日期;否则,这是前一个工作日
  • 午休时间的实际数量等于重新计算的日期之间的差值,每小时一次。 以下是伪代码:

如果(!in_数组($startDate->format('l')、数组('Sunday'、'Saturday'))和($startDate->format('g')<12){
$startForLunch=$startDate;
}
否则{
$startForLunch=新日期时间($start,+1天”);
while(在数组中($startDate->format('l'),数组('Sunday','Saturday')){
$startForLunch->add('1天');
}
}
如果(!in_数组($endDate->format('l')、数组('Sunday'、'Saturday'))和($endDate->format('g')>13){
$endfor午餐=$end;
}
否则{
$endfor午餐=新日期时间($endDate,'-1天');
while(在数组($endDate->format('l')、数组('Sunday'、'Saturday'))中){
$endfor午餐->添加(“-1天”);
}
}
$午餐时段=$endfor午餐-$startForLunch+1;

您是否定义了午休时间或午休时间是一个静态数字?@Mech是的,定义了午休时间是从上午12:00到下午13:00/1:00P的一个小时,您是否希望显示午休时间是在设定的时间?即08:00-12:00,13:00-17:00?否则,仅从上午12:00到下午13:00的一个小时it@Mech我想把午休和假期排除在预算之外总小时数差异代码正常现在唯一的问题是假期膨胀如果你的“holydays”不只是周末你可以在函数中添加一个参数来定义你的holydays我只需更新我的答案我希望这就是你要找的谢谢这就是我要找的!我在EndFor午餐=new DateTime($endDate,“-1天”)上收到一个错误;错误为未捕获的异常“exception”,消息为“DateTime:::_construct()要求参数1为字符串,对象givei应该使用发送到函数中的参数。它是“伪代码”,不是真实的。我只是尝试编写一些可读性足够强的内容,以便您遵循逻辑并开发适当的解决方案。
in_array($date->format('Y-m-d'), $holyDays)
function business_hours($start, $end,$holyDays = null){

    $startDate = new DateTime($start);
    $endDate = new DateTime($end);
    $periodInterval = new DateInterval( "PT1H" );

    $period = new DatePeriod( $startDate, $periodInterval, $endDate );
    $count = 0;



    foreach($period as $date){
        $startofday = clone $date;
        $startofday->setTime(8,00);
        $endofday = clone $date;
        $endofday->setTime(17,00);

        //just some var to use in conditional check
        $notHolyday = true;

        //now check the array of holyday and check if in range dates is same with holydays we have
        if($holyDays != null && is_array($holyDays) && in_array($date->format('Y-m-d'), $holyDays)){
            $notHolyday = false;
        }

        if($date > $startofday && $date <= $endofday && !in_array($date->format('l'), array('Sunday','Saturday')) && ($date->format('H') <= 12 || $date->format('H') > 13) && $notHolyday){
            $count++;

        }

    }
    echo $count;
}

$start = '2020-02-14 08:00:00';
$end = '2020-02-19 08:00:00';
$holyDays = array('2020-02-17','2020-02-18');
$count = business_hours($start,$end,$holyDays);

echo $count;

    if(!in_array($startDate->format('l'), array('Sunday','Saturday')) && ($startDate->format('g') < 12) {
        $startForLunch = $startDate;
    }
    else {
        $startForLunch = new DateTime($start, '+1 day');
        while(in_array($startDate->format('l'), array('Sunday','Saturday'))){
            $startForLunch->add('1 day');
        }
    }

    if(!in_array($endDate->format('l'), array('Sunday','Saturday')) && ($endDate->format('g') > 13) {
        $endForLunch = $end;
    }
    else {
        $endForLunch = new DateTime($endDate, '-1 day');
        while(in_array($endDate->format('l'), array('Sunday','Saturday'))){
            $endForLunch->add('-1 day');
        }
    }
    $lunchPeriods = $endForLunch - $startForLunch + 1;