ogsoft-example/app/Services/Utils/DurationConvertor.php

65 lines
2.2 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Services\Utils;
use Brick\DateTime\Duration;
use Brick\DateTime\LocalTime;
/*
* Converts given dates and times into a Duration object.
*/
class DurationConvertor
{
public function __construct()
{
}
/**
* Convert a given duration into working hours considering the given start and end workday. Duration is calculated from startWorkday
* @param Duration $duration
* @param LocalTime $startWorkday
* @param LocalTime $endWorkday
* @param \DateTimeInterface $startTime
* @return DurationConvertorResult
*/
public function convertIntoWorkDuration(Duration $duration, LocalTime $startWorkday, LocalTime $endWorkday, \DateTimeInterface $startTime): DurationConvertorResult
{
if ($endWorkday->isEqualTo($startWorkday)) {
throw new \InvalidArgumentException("Start and end workday must be different");
}
$workDuration = $duration;
$endDuration = Duration::zero();
$workDaySeconds = $endWorkday->toSecondOfDay() - $startWorkday->toSecondOfDay();
// handle first day
$startDateTime = \DateTimeImmutable::createFromInterface($startTime)->setTime($startWorkday->getHour(), $startWorkday->getMinute());
$availSecondsFirstDay = $workDaySeconds - ($startTime->getTimestamp() - $startDateTime->getTimestamp());
if ($availSecondsFirstDay >= $workDuration->toSeconds()) {
// first day is enough time
$endDuration->plusSeconds($workDaySeconds - $availSecondsFirstDay);
return new DurationConvertorResult(
false,
$endDuration->plusSeconds($workDuration->toSeconds())
);
} else {
$workDuration = $workDuration->minusSeconds($availSecondsFirstDay);
$endDuration = $endDuration->plus(Duration::ofDays(1));
}
while ($workDuration->toSeconds() > $workDaySeconds) {
$endDuration = $endDuration->plus(Duration::ofDays(1));
$workDuration = $workDuration->minusSeconds($workDaySeconds);
}
return new DurationConvertorResult(
true,
$endDuration->plus($workDuration)
);
}
}