首页 > 解决方案 > 计算PHP中的工作时间时差

问题描述

我想计算编码日期和完成日期之间的小时数。到目前为止,我可以计算两个日期时间之间的时差,不包括周六和周日。我的问题是我需要排除午休时间(上午 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
?>

根据我的代码,我将工作时间设置为 8:00 到 17:00,然后排除周六和周日。根据我的示例,输出将为 9(包括午休时间)。如何排除午休和节假日?

更新

完成时间可以超过1天。例如,开始日期/时间为 2020-02-14 08:00:00,完成时间为 2020-02-19 08:00:00,输出为 27 小时。该计算应排除每天中午 12:00 至下午 1:00 和节假日之间的午休时间。

更新
我添加了一系列假期,如何排除这些假期?

标签: php

解决方案


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

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

    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;


推荐阅读