-1

The following code creates a PHP DatePeriod object based off user inputs. The first iteration of the loop runs, but the second returns this error: PHP Fatal error: Call to a member function format() on a non-object. I cannot see what's causing the error.

I hope to use this to fill an array with irregular recurring dates. ie. "Second Sunday of this month", "Last Friday of this month".

$raw_dates['starting'] = DateTime::createFromFormat( 'Ymd', $starting_date );
$raw_dates['ending'] = DateTime::createFromFormat( 'Ymd', $ending_date );

if ( 'Monthly' == $frequency ) {
    $recurances = $raw_dates['starting']->diff($raw_dates['ending']);
    $recurances = $recurances->m;
    $i = 'P1M';
    $interval = new DateInterval( $i );
    $period = new DatePeriod( $raw_dates['starting'], $interval, $recurances );
    $string = $monthly_recurring_week.' '.$monthly_recurring_day.' of ';

    foreach ( $period as $date ) {
        $string .= $date->format( 'F Y');
        $occurance = strtotime( $string );
        $raw_occurance = DateTime::createFromFormat( 'U', $occurance );
        $finished_date = $raw_occurance->format( 'Ymd' );
        $occurances[] = array(
            'sm_set_starts' => $finished_date,
            'sm_set_ends' => $finished_date
        );
    }

}

This line is the one throwing the error on the second iteration: $finished_date = $raw_occurance->format( 'Ymd' ); But I think the might be earlier with my DatePeriod object.

This is a dump of the DatePeriod object:

object(DatePeriod)#51 (6) {
  ["start"]=>
  object(DateTime)#53 (3) {
    ["date"]=>
    string(26) "2015-07-01 14:34:01.000000"
    ["timezone_type"]=>
    int(3)
    ["timezone"]=>
    string(3) "UTC"
  }
  ["current"]=>
  NULL
  ["end"]=>
  NULL
  ["interval"]=>
  object(DateInterval)#55 (15) {
    ["y"]=>
    int(0)
    ["m"]=>
    int(1)
    ["d"]=>
    int(0)
    ["h"]=>
    int(0)
    ["i"]=>
    int(0)
    ["s"]=>
    int(0)
    ["weekday"]=>
    int(0)
    ["weekday_behavior"]=>
    int(0)
    ["first_last_day_of"]=>
    int(0)
    ["invert"]=>
    int(0)
    ["days"]=>
    bool(false)
    ["special_type"]=>
    int(0)
    ["special_amount"]=>
    int(0)
    ["have_weekday_relative"]=>
    int(0)
    ["have_special_relative"]=>
    int(0)
  }
  ["recurrences"]=>
  int(3)
  ["include_start_date"]=>
  bool(true)
}
Andrew
  • 153
  • 1
  • 11

1 Answers1

0

Following John Conde suggestion to use DateTime and based on Sverri M Olsen's answer to this SO question I discovered DateInterval:createFromDateString.

This is the working code for this question

if ( 'Monthly' == $frequency ) {
    $string = $monthly_recurring_week.' '.$monthly_recurring_day.' of next month';
    $interval = DateInterval::createFromDateString( $string );
    $period   = new DatePeriod($raw_dates['starting'], $interval, $raw_dates['ending'], DatePeriod::EXCLUDE_START_DATE);

    foreach($period as $time) {
        $occurances[] = array(
            'sm_set_starts' => $time->format( 'Ymd' ),
            'sm_set_ends' => $time->format( 'Ymd' )
        );
    }

}

I think it's worth noting that when looping through the DatePeriod object the "of next month" part of the date string is relative to the current interval, and not the start date, which is what I was doing in the original post.

Community
  • 1
  • 1
Andrew
  • 153
  • 1
  • 11