Lo que puede hacer es hacer un DatePeriod
de intervalos de 1 segundo (supongo que esto es crítico para el negocio, por lo que tiene que ser al segundo) y verifique si cada segundo está dentro del horario comercial del día. Si es así, réstelo del total.
Sin embargo, esto es terriblemente ineficiente. Por ejemplo, solo por un día completo tendrías que hacer 86400 cheques. Se vuelve lento rápidamente . Tal vez, en su lugar, pueda usar un intervalo de 1 minuto o incluso de 1 hora si los requisitos de su negocio lo permiten, y hacer algunas estimaciones. De todos modos, así es como puedes hacer esto:
<?php
use Carbon\Carbon;
$startTime = Carbon::create(2017, 9, 10, 8, 20, 0);
$endTime = Carbon::create(2017, 9, 10, 18, 35, 0);
$duration = $startTime->diffInSeconds($endTime, true);
$interval = new DateInterval("PT1S");
$period = new DatePeriod($startTime, $interval, $endTime);
$secondsToSubtract = 0;
foreach ($period as $second) {
$businessStart = clone $second;
$businessStart->setTime(8, 0); // start business day
$businessEnd = clone $second;
$businessEnd->setTime(17, 0); // end business day
if (!($second > $businessStart && $second < $businessEnd)) { // if the second is not a "business second", subtract it
$secondsToSubtract++;
}
}
var_dump($secondsToSubtract);
$realDuration = $duration - $secondsToSubtract;
var_dump($realDuration);
No menciona si los fines de semana son o no días hábiles para usted. Si lo son, simplemente verifique si el día actual en la iteración es sábado o domingo y reste todos esos segundos.
Puede hacer muchas optimizaciones aquí (almacenar en caché el día, por ejemplo), pero debería llevarlo en la dirección correcta.
(No puedo mostrarte una demostración porque no puedo use Carbon
en los proveedores típicos)