3v4l.org

run code in 300+ PHP versions simultaneously
<?php abstract class AbstractDateEntity { protected \DateTimeInterface $start; protected \DateTimeInterface $stop; protected WorkHours $workHours; public function __construct(string $start, string $stop, \DateTimeZone $tmz = null) { $tmz = $tmz ?? new DateTimeZone('Europe/Berlin'); $this->start = new DateTimeImmutable($start, $tmz); $this->stop = new DateTimeImmutable($stop, $tmz); $this->workHours = new WorkHours($this->getHours()); } public function getStart(): DateTimeInterface { return $this->start; } public function getStop(): DateTimeInterface { return $this->stop; } public function getDiff(): DateInterval { return $this->start->diff($this->stop); } public function getPeriod(DateInterval $interval = null): DatePeriod { return new DatePeriod($this->start, $interval ?? new DateInterval('PT1H'), $this->stop); } public function getWorkHours(): WorkHours { return $this->workHours; } public function getHours(): string { $diff = $this->getDiff(); $h = bcmul($diff->format('%a'), '24', 2); $mins = bcdiv($diff->i, '60', 2); return bcadd(bcadd($h, $diff->h, 2), $mins, 2); } } class Shift extends AbstractDateEntity { private array $absences = []; private array $absentPeriods = []; public function getAbsences(): array { return $this->absences; } public function addAbsence(Absence $absence): self { $this->absences[] = $absence; $this->workHours->addOff($absence->getWorkHours()->getTotal()); $this->absentPeriods = array_merge($this->absentPeriods, iterator_to_array($absence->getPeriod())); //here you can add logic for absences return $this; } public function isAbsent(DateTimeInterface $date): bool { return in_array($date, $this->absentPeriods); } public function getAbsentPeriods(): array { return $this->absentPeriods; } } class Absence extends AbstractDateEntity{} class WorkHours { private string $total = '0'; private string $off = '0'; private string $on = '0'; public function __construct(string $total = null, string $off = null) { if (null !== $total) { $this->total = $this->on = $total; } if (null !== $off) { $this->addOff($off); } } public function getTotal(): string { return $this->total; } public function addTotal(string $amount, int $p = 2): self { $this->total = bcadd($this->total, $amount, $p); $this->addOn($amount, $p); return $this; } public function getOff(): string { return $this->off; } public function addOff(string $amount, int $p = 2): self { $this->off = bcadd($this->off, $amount, $p); $this->subOn($amount, $p); return $this; } public function getOn(): string { return $this->on; } public function addOn(string $amount, int $p = 2): self { $this->on = bcadd($this->on, $amount, $p); return $this; } public function subOn(string $amount, int $p = 2): self { $this->on = bcsub($this->on, $amount, $p); return $this; } } class WorkSchedule { private array $shifts = []; private WorkHours $workHours; public function __construct() { $this->workHours = new WorkHours(); } public function getShifts(): array { return $this->shifts; } public function addShift(Shift $shift): self { $this->shifts[] = $shift; $this->workHours->addTotal($shift->getWorkHours()->getTotal()); $this->workHours->addOff($shift->getWorkHours()->getOff()); //here you can add logic to calculate the shift details return $this; } public function getWorkHours(): WorkHours { return $this->workHours; } } $tmz = new DateTimeZone('Europe/Berlin'); $workSchedule = (new WorkSchedule()) ->addShift( (new Shift("2022-04-02 10:00:00", "2022-04-02 20:00:00", $tmz)) ->addAbsence(new Absence("2022-04-02 15:00:00", "2022-04-02 17:00:00", $tmz), ) ) ->addShift( (new Shift("2022-04-03 7:00:00", "2022-04-03 17:00:00", $tmz)) ->addAbsence(new Absence("2022-04-03 16:00:00", "2022-04-03 17:00:00", $tmz)) ) ->addShift( (new Shift("2022-04-04 9:00:00", "2022-04-04 19:00:00", $tmz)) ->addAbsence(new Absence("2022-04-04 9:00:00", "2022-04-04 12:00:00", $tmz)) ); //report for totals $hrs = $workSchedule->getWorkHours(); vprintf("Total Hours Scheduled: %d\nTotal Hours Absent: %d\nTotal Hours Worked: %d\n\n", [ $hrs->getTotal(), $hrs->getOff(), $hrs->getOn(), ]); //reporting for each shift in the schedule foreach ($workSchedule->getShifts() as $shift) { vprintf("Shift %s - %s\n", [ $shift->getStart()->format('Y-m-d H:i:s'), $shift->getStop()->format('Y-m-d H:i:s') ]); $hrs = $shift->getWorkHours(); vprintf("Hours Scheduled: %d, Hours Absent: %d , Hours Worked: %d\n", [ $hrs->getTotal(), $hrs->getOff(), $hrs->getOn(), ]); //iterate over each workhour date $shiftPeriod = $shift->getPeriod(); foreach ($shiftPeriod as $shiftDate) { if ($shift->isAbsent($shiftDate)) { //was absent at this hour - do something? printf("Absent: %s\n", $shiftDate->format('H:i:s')); continue; } //was actively working at this hour - do something printf("Worked: %s\n", $shiftDate->format('H:i:s')); } echo PHP_EOL; }
Output for git.master, git.master_jit, rfc.property-hooks
Total Hours Scheduled: 30 Total Hours Absent: 6 Total Hours Worked: 24 Shift 2022-04-02 10:00:00 - 2022-04-02 20:00:00 Hours Scheduled: 10, Hours Absent: 2 , Hours Worked: 8 Worked: 10:00:00 Worked: 11:00:00 Worked: 12:00:00 Worked: 13:00:00 Worked: 14:00:00 Absent: 15:00:00 Absent: 16:00:00 Worked: 17:00:00 Worked: 18:00:00 Worked: 19:00:00 Shift 2022-04-03 07:00:00 - 2022-04-03 17:00:00 Hours Scheduled: 10, Hours Absent: 1 , Hours Worked: 9 Worked: 07:00:00 Worked: 08:00:00 Worked: 09:00:00 Worked: 10:00:00 Worked: 11:00:00 Worked: 12:00:00 Worked: 13:00:00 Worked: 14:00:00 Worked: 15:00:00 Absent: 16:00:00 Shift 2022-04-04 09:00:00 - 2022-04-04 19:00:00 Hours Scheduled: 10, Hours Absent: 3 , Hours Worked: 7 Absent: 09:00:00 Absent: 10:00:00 Absent: 11:00:00 Worked: 12:00:00 Worked: 13:00:00 Worked: 14:00:00 Worked: 15:00:00 Worked: 16:00:00 Worked: 17:00:00 Worked: 18:00:00

This tab shows result from various feature-branches currently under review by the php developers. Contact me to have additional branches featured.

Active branches

Archived branches

Once feature-branches are merged or declined, they are no longer available. Their functionality (when merged) can be viewed from the main output page


preferences:
56.15 ms | 1500 KiB | 4 Q