Search code examples
phpdatetimestampschedule

PHP Howto generate timestamps in a timeframe with a specific weekly schedule?


I have to find a way to generate timestamps between two dates with a strickt weekly time-schedule. (see the example below)

Weekly time-schedule

Mo - skip
Tu - 18.30
We - 18.30
Th - 19.30
Fr - 19.30
Sa - 14.00 & 19.30
So - 15.00

And I wanna generate all timestamps between the 2020-05-01 and the 2020-05-31.

My idea is to use DatePeriod to generate all timestamps from every day's time in the set timeframe. (Get the first Tuesday from the starting date, add the time and use DatePeriod to get all Tuesdays in the timeframe - that with every time in the weekly time schedule) Then I could merge the arrays and sort it.

I'm wondering if there is a simpler way to do that? Any idea?


Solution

  • The times of the week can be saved in an array with relative date expressions.

    $times = [
        "Tue 18:30",
        "Wed 18:30",
        "Thu 19:30",
        "Fri 19:30",
        "Sat 14:00",
        "Sat 19:30",
        "Sun 15:00",
    ];
    

    All of these times are added to the $curDate and after a check the smallest of these values ​​is saved as $nextDate. This continues in a while loop until the end date. I wrote a function for that.

    function schedulePeriod(array $times, $start, $end)
    {
        $period = [];
        $curDate = clone $start;
        while(true){
            $nextDate = clone $end; 
            foreach($times as $modifier){
                $nextTime = (clone $curDate)->modify($modifier);
                if($nextTime > $curDate AND $nextTime < $nextDate){
                    $nextDate = $nextTime; 
                }
            }
            if($nextDate >= $end) break;
            $period[] = $nextDate;
            $curDate = $nextDate;
        }
        return $period;
    }
    

    The result of this function is a array of datetime objects.

    $start = date_create("2020-05-01 00:00");
    $end =  date_create("2020-06-01 00:00");
    $period = schedulePeriod($times, $start, $end);
    
    echo '<pre>';
    var_export($period);
    

    The output (reduced):

    array (
      0 => 
      DateTime::__set_state(array(
         'date' => "2020-05-01 19:30:00.000000",
         'timezone_type' => 3,
         'timezone' => "Europe/Berlin",
      )),
      1 => 
      DateTime::__set_state(array(
         'date' => "2020-05-02 14:00:00.000000",
         'timezone_type' => 3,
         'timezone' => "Europe/Berlin",
      )),
      2 => 
      DateTime::__set_state(array(
         'date' => "2020-05-02 19:30:00.000000",
         'timezone_type' => 3,
         'timezone' => "Europe/Berlin",
      )),
      3 => 
      DateTime::__set_state(array(
         'date' => "2020-05-03 15:00:00.000000",
         'timezone_type' => 3,
         'timezone' => "Europe/Berlin",
      )),
    

    The dateTime format method can be used to achieve a desired date format.