src/TimeOverlapCalculator.php
public function getNonOverlappedTimeSlots(
        TimeSlotInterface $baseTimeSlot,
        array $overlappingTimeSlots,
        TimeSlotGeneratorInterface $timeSlotGenerator
    ) {
        $baseTimeSlots = [
            $timeSlotGenerator->createTimeSlot($baseTimeSlot->getStart(), $baseTimeSlot->getEnd()),
        ];

        foreach ($overlappingTimeSlots as $overlappingTimeSlot) {
            $freeTimeSlots = [];
            foreach ($baseTimeSlots as $timeSlot) {
                $freeTimeSlots =  array_merge(
                    $freeTimeSlots,
                    $this->fetchNonOverlappedTimeSlots($timeSlot, $overlappingTimeSlot, $timeSlotGenerator)
                );
            }

            $baseTimeSlots = $freeTimeSlots;
        }

        return $baseTimeSlots;
    }
public function getNonOverlappedTimeSlots(
        TimeSlotInterface $baseTimeSlot,
        array $overlappingTimeSlots,
        TimeSlotGeneratorInterface $timeSlotGenerator
    ) {
        $baseTimeSlots = [
            $timeSlotGenerator->createTimeSlot($baseTimeSlot->getStart(), $baseTimeSlot->getEnd()),
        ];

        foreach ($overlappingTimeSlots as $overlappingTimeSlot) {
            $freeTimeSlots = [];
            foreach ($baseTimeSlots as $timeSlot) {
                $freeTimeSlots =  array_merge(
                    $freeTimeSlots,
                    $this->fetchNonOverlappedTimeSlots($timeSlot, $overlappingTimeSlot, $timeSlotGenerator)
                );
            }

            $baseTimeSlots = $freeTimeSlots;
        }

        return $baseTimeSlots;
    }
Create an array of non overlapped time slots

@param TimeSlotInterface          $baseTimeSlot
@param TimeSlotInterface[]        $overlappingTimeSlots
@param TimeSlotGeneratorInterface $timeSlotGenerator

@return TimeSlotInterface[]