php 计算工作时间(工作日和星期六不同)

cmssoen2  于 2022-12-17  发布在  PHP
关注(0)|答案(1)|浏览(288)

我尝试了@ebelendez的代码 * 计算两个日期之间的工作时间 *,但是我对如何设置周六的值为3小时(08:00-11:00)感到困惑。例如,工作日每天的工作时间是8小时(不包括1小时休息时间),假设我想得到从周四到周六的总工作时间,预期结果将是19小时。
我是这么做的。有人能帮我吗?

$from = '2022-04-21 07:00:00';
$to = '2022-04-23 16:00:00';

echo abs(get_working_hours($from, $to));

function get_working_hours($from,$to){
    //config
    $ini_time = [7,0]; //hr, min
    $end_time = [16,0]; //hr, min
    //date objects
    $ini = date_create($from);
    $ini_wk = date_time_set(date_create($from),$ini_time[0],$ini_time[1]);
    $end = date_create($to);
    $end_wk = date_time_set(date_create($to),$end_time[0],$end_time[1]);
    //days
    $workdays_arr = get_workdays($ini,$end);
    $workdays_count = count($workdays_arr);
    $workday_seconds = (($end_time[0] * 60 + $end_time[1]) - ($ini_time[0] * 60 + $ini_time[1])) * 60 - 3600;
    //get time difference
    $ini_seconds = 0;
    $end_seconds = 0;
    if(in_array($ini->format('Y-m-d'),$workdays_arr)) $ini_seconds = $ini->format('U') - $ini_wk->format('U');
    if(in_array($end->format('Y-m-d'),$workdays_arr)) $end_seconds = $end_wk->format('U') - $end->format('U');
    $seconds_dif = $ini_seconds > 0 ? $ini_seconds : 0;
    if($end_seconds > 0) $seconds_dif += $end_seconds;
    //final calculations
    $working_seconds = ($workdays_count * $workday_seconds) - $seconds_dif;
    return $working_seconds / 3600; //return hrs
}

function get_workdays($ini,$end){
    //config
    $skipdays = [0]; //sunday:0
    $skipdates = []; 
    //vars
    $current = clone $ini;
    $current_disp = $current->format('Y-m-d');
    $end_disp = $end->format('Y-m-d');
    $days_arr = [];
    //days range
    while($current_disp <= $end_disp){
        if(!in_array($current->format('w'),$skipdays) && !in_array($current_disp,$skipdates)){
            $days_arr[] = $current_disp;
        }
        $current->add(new DateInterval('P1D')); //adds one day
        $current_disp = $current->format('Y-m-d');
    }
    return $days_arr;
}
5ssjco0h

5ssjco0h1#

您的代码和相关答案似乎过于复杂。我们真正需要的是:
1.配置每天应计算的小时数;
1.创建一个可迭代的DatePeriod(周期中的每个日期都有DateTime对象);
1.重复日期,查找每天应该计算多少小时,然后求和。

class CountWorkingHours
{
    // Define hours counted for each day:
    public array $hours = [ 
        'Mon' => 8, 
        'Tue' => 8, 
        'Wed' => 8, 
        'Thu' => 8, 
        'Fri' => 8, 
        'Sat' => 3, 
        'Sun' => 0
    ];

    // Method for counting the hours:
    public function get_hours_for_period(string $from, string $to): int
    {
        // Create DatePeriod with requested Start/End dates:
        $period = new DatePeriod(
            new DateTime($from), 
            new DateInterval('P1D'), 
            new DateTime($to)
        );
        
        $hours = [];

        // Loop over DateTime objects in the DatePeriod:
        foreach($period as $date) {
            // Get name of day and add matching hours:
            $day = $date->format('D');
            $hours[] = $this->hours[$day];
        }
        // Return sum of hours:
        return array_sum($hours);
    }
}
  • Source @位存储桶
  • 使用情况(返回给定时间段内的工作小时数整数):
$cwh = new CountWorkingHours();
$hours = $cwh->get_hours_for_period('2022-04-21 07:00:00', '2022-04-30 16:00:00');
// = 62

如果需要将公共假日等例外情况计入标准每周小时数,则可以在期间循环中添加“跳过日期”检查。例如,使用$skip_dates属性,其中包含非工作日数组,然后在增加给定日期的工作小时数之前检查!in_array($date->format('Y-m-d'), $this->skip_dates)
另外,这段代码假设 * 你正在计算整个工作日 *。如果你的开始或结束时间是在一个工作日的中间定义的,那就不会被考虑在内。(如果你想考虑这个因素,你必须配置每天的工作时间,代码在计算开始和结束日期时必须考虑到这一点。对于当前的目的来说,这似乎是一个不必要的练习。)

相关问题