PHP посчитать количество секунд рабочего времени между двумя датами, с учетом рабочего графика и праздничных дней
Может у кого есть готовое решение как это реализовать? Допустим есть рабочий график:
- Понедельник - пятница с 8 до 20
- Суббота с 8 до 17
И есть две даты, нужно посчитать сколько секунд рабочего времени прошло между ними, с учетом графика рабочего времени: 25-12-2020 07:00:00 и 30-12-2020 18:02:01
Праздничные дни думаю можно будет указать в массив. Пробовал код ниже, работает но считает только по одному рабочему графику, не учитывая что в субботу совсем другое время рабочее
function work_hours_diff($date1, $date2)
{
if ($date1 > $date2)
{
$tmp = $date1;
$date1 = $date2;
$date2 = $tmp;
unset($tmp);
$sign = - 1;
}
else return 0;
if ($date1 == $date2) return 0;
$days = 0;
$working_days = array(
1,
2,
3,
4,
5,
6
);
$working_hours = array(
8,
20
);
$current_date = $date1;
$beg_h = floor($working_hours[0]);
$beg_m = ($working_hours[0] * 60) % 60;
$end_h = floor($working_hours[1]);
$end_m = ($working_hours[1] * 60) % 60;
if (!in_array(date('w', $current_date) , $working_days))
{
$current_date = mktime($beg_h, $beg_m, 0, date('n', $current_date) , date('j', $current_date) , date('Y', $current_date));
while (!in_array(date('w', $current_date) , $working_days))
{
$current_date += 24 * 3600;
}
}
else
{
$date0 = mktime($beg_h, $beg_m, 0, date('n', $current_date) , date('j', $current_date) , date('Y', $current_date));
if ($current_date < $date0) $current_date = $date0;
$date3 = mktime($end_h, $end_m, 0, date('n', $current_date) , date('j', $current_date) , date('Y', $current_date));
if ($date3 < $current_date)
{
$current_date += 24 * 3600;
$current_date = mktime($beg_h, $beg_m, 0, date('n', $current_date) , date('j', $current_date) , date('Y', $current_date));
while (!in_array(date('w', $current_date) , $working_days))
{
$current_date += 24 * 3600;
}
}
}
$date0 = mktime($end_h, $end_m, 0, date('n', $current_date) , date('j', $current_date) , date('Y', $current_date));
$seconds = $date0 - $current_date;
$date3 = mktime($beg_h, $beg_m, 0, date('n', $date2) , date('j', $date2) , date('Y', $date2));
while ($current_date < $date3)
{
$current_date += 24 * 3600;
if (in_array(date('w', $current_date) , $working_days)) $days++;
}
$days--;
$date0 = mktime($beg_h, 0, 0, date('n', $date2) , date('j', $date2) , date('Y', $date2));
if ($date2 < $date0)
{
}
else
{
$date3 = mktime($end_h, $end_m, 0, date('n', $date2) , date('j', $date2) , date('Y', $date2));
if ($date2 > $date3) $date2 = $date3;
$tmp = $date2 - $date0;
$seconds += $tmp;
}
$seconds += 3600 * ($working_hours[1] - $working_hours[0]) * $days;
return $seconds;
}
date_default_timezone_set("Europe/Kaliningrad");
$dt2 = strtotime("25-12-2020 07:00:00");
$dt1 = strtotime("30-12-2020 18:02:01");
$seconds = work_hours_diff($dt1, $dt2);
var_dump($seconds);
Делал ещё один вариант, но там каждую секунду приходится проверять соответствует ли она условию, и добавлять в счетчик, что очень не правильно как я думаю, хотя этот вариант и работает...
<?php
date_default_timezone_set('Europe/Kaliningrad');
$start = '2020-12-24 07:00:00';
$end = '2020-12-25 08:40:00';
$startDate = new DateTime($start);
$endDate = new DateTime($end);
$periodInterval = new DateInterval("PT1S");
$period = new DatePeriod($startDate, $periodInterval, $endDate);
$count = 0;
foreach ($period as $date)
{
if($date->format('N') != 7){ //Исключим воскресенье
if($date->format('N') == 6){ //Пятница
$time_work = ['08','09','10','11','12','13','14','15','16','17'];
}else{//Остальные дни
$time_work = ['08','09','10','11','12','13','14','15','16','17','18','19','20'];
}
if(in_array($date->format('H') ,$time_work)){
$count++;
}
}
}
echo 'Прошло часов всего: '.floor($count / 3600).PHP_EOL;
echo 'Прошло минут всего: '.($count / 60).PHP_EOL;
echo 'Прошло секунд всего: '.$count.PHP_EOL;