public function findOpening($startDay = 0, $endDay = 7, $fileRate = 1, $all = false, $startTime = null)
    {
        $openings = [];
        for ($day = $startDay; $day <= $endDay; ++$day) {
            if (0 === $day) {
                // Current day.
                if ($startTime && $startTime instanceof \DateTime) {
                    $date = clone $startTime;
                } else {
                    $date = new \DateTime();
                }
            } else {
                // Future days.
                // Use noon to begin to evaluate days in the future to avoiding timezones during day checks.
                $date = new \DateTime('noon +'.$day.' day');
            }
            try {
                // Initialize the range (will expand as appropriate later).
                $start = clone $date;
                $end   = clone $date;

                // Evaluate that the client is open this day of the week.
                $hours = $this->evaluateDay(true, $date);

                // Evaluate that the client isn't closed by an excluded date rule.
                $this->evaluateExclusions($date);

                // Push the end time to the correct time for this client's hours.
                $timeTill = !empty($hours->timeTill) ? $hours->timeTill : '23:59';
                $end->setTimezone($this->timezone);
                $end->modify($timeTill.':59');

                // Current day: Evaluate that there is still time today to send.
                if (0 == $day && $this->now > $end) {
                    // Continue to the next day.
                    continue;
                }

                // Pull the start time to the correct time for this day and schedule.
                $timeFrom = !empty($hours->timeFrom) ? $hours->timeFrom : '00:00';
                $start->setTimezone($this->timezone);
                $start->modify($timeFrom);

                if ('file' === $this->contactClient->getType()) {
                    // Evaluate if we have exceeded allowed file count for this day.
                    $fileCount = $this->evaluateFileRate($fileRate, $date);

                    // If we have already built a file in this day and can send more...
                    if ($fileCount > 0 && $fileRate > 1) {
                        // Push the start time to the next available slot in this day.
                        $daySeconds = $end->format('U') - $start->format('U');
                        if ('00:00' === $timeFrom && '23:59' === $timeTill) {
                            // Avoid sending 2 files at midnight.
                            $segmentSeconds = intval($daySeconds / $fileRate);
                        } else {
                            // Send at opening and closing times, spreading the rest of the day evenly.
                            $segmentSeconds = intval($daySeconds / ($fileRate - 1));
                        }
                        // Push start time to the next segment.
                        $start->modify('+'.($segmentSeconds * $fileCount).' seconds');
                    }
                }

                // Start time should not be in the past.
                if (0 === $day && $start < $this->now) {
                    // Must be done after rate has been applied.
                    $start = $this->now;
                }

                $openings[] = [$start, $end];
                if (!$all) {
                    break;
                }
            } catch (\Exception $e) {
                if ($e instanceof ContactClientException) {
                    // Expected.
                } else {
                    throw $e;
                }
            }
        }

        return $openings;
    }