MODX Community

Exclude dates from a php DatePeriod output

Working on a snippet that will generate a list of weekdays over the next couple of months. Within this list I wish to exclude a number of specific dates such as Public Holidays. These excluded dates will eventually be provided through a MIGX output (not sure how to do this bit yet).

So far I have been working on getting list of days and am stuck on excluding certain dates. I found a discussion on [https://stackoverflow.com/questions/16132356/php-exclude-dates-from-a-date-range](http://Stack Overflow) and have tried to implement it but it does not seem to be working for me. I think that the issue maybe in the way that the $exclude array contents.

<?php
/**
 * Function will give the day ($day) of the week (say monday) for the next 3 ($interval) months
 * current date (as in today) is excluded
 * @param int $interval number of months, e.g. 2
 * @param $day - expected to be a day of the week, e.g. Monday
 * @return object of type DatePeriod
*/
function getRepeatingDays($interval, $day) {
	 $theDay = 'next '.$day;
	 $endDate = new DateTime();
	 $interval = new DateInterval("P".$interval."M");
	 $endDate->add($interval);
	 return new DatePeriod(
		  new DateTime(),
		  DateInterval::createFromDateString($theDay),
		  $endDate,
		  DatePeriod::EXCLUDE_START_DATE
	 );
}

// $dateList is a call to get a list of mondays for the next 2 months
$dateList = getRepeatingDays("2", "monday");

// $exclude is an array of dates that are to be excluded from the results given by $dateList
$exclude = array(
	 new DateTime('6/17/19'),
	 new DateTime('8/7/19'),
);

// iterate over $dateList and remove the excluded dates. Output the non-excluded dates
foreach($dateList as $newDate){
	 if(!in_array($newDate, $exclude)) {
	 		//add to $output the date string as Monday, 03 June 2019 and add a html line break
		  $output.= $newDate->format("l, d F Y")."<br>";
	 }   
}

// output a list of dates
return $output;

So my issues are:

  • how to exclude specific dates from a php DatePeriod object output
  • how to manipulate the output from a MIGX TV list of dates

Looking forward to your help. Many thanks.

This was a really interesting problem. I couldn’t make your method work, but here’s another approach that I think uses more readable code and has the holidays built in for any year.

I tested it and at least it works for memorial day. :wink:

 * @param string $curYear - current year, e.g. "2019"
 * @return array - array of holiday timestamps
 */

function getHolidays($curYear) {
    $holidays = array();
    $holidays[] = strtotime("january $curYear third monday"); //marthin luther king jr.day
    $holidays[] = strtotime("february $curYear third monday"); //presidents day
    $holidays[] = strtotime(easter_date($curYear)); // easter
    $MDay = date('Y-m-d', strtotime("may $curYear first monday")); // memorial day (set below)
      $eMDay = explode("-", $MDay);
      $year = $eMDay[0];
      $month = $eMDay[1];
      $day = $eMDay[2];

      while ($day <= 31) {
          $day = $day + 7;
      }
      if ($day > 31) {
          $day = $day - 7;
      }

    $holidays[] = strtotime($year . '-' . $month . '-' . $day); // memorial day
    $holidays[] = strtotime("september $curYear first monday");  //labor day
    $holidays[] = strtotime("october $curYear third monday"); //columbus day
    $TH = date('Y-m-d', strtotime("november $curYear first thursday")); // thanks giving (set below)
      $eTH = explode("-", $TH);
      $year = $eTH[0];
      $month = $eTH[1];
      $day = $eTH[2];

      while ($day <= 30) {
          $day = $day + 7;
      }
      if ($day > 30) //watch out for the days in the month November only have 30
      {
          $day = $day - 7;
      }

    $holidays[] = strtotime($year . '-' . $month . '-' . $day); // Thanksgiving

    return $holidays;
    
}

/**
 * @param int $t - timestamp
 * @param $holidays - array of holiday timestamps
 * @return bool - true for holidays or false
 */
function isHoliday($t, $holidays) {
    return (in_array($t, $holidays));
}

$curYear = date("Y");//current year
$holidays = getHolidays($curYear);
$weekdayNames = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday');
$output = "";

/* Get day of year */
$today = date('z');
$output .= "\n<br>Today is day# " . $today;

/* $weekdays will be an array of upcoming weekdays that are not holidays */
$weekdays = array();

for ($days=$today; $days < (int) $today + 20; $days++) {
    /* Get timestamp for given day */
    $timestamp = strtotime("January 1st +" . ($days) . " days");

    /* If $timestamp is non-holiday weekday, add it to the $weekdays array */
    if (in_array(strftime("%A",$timestamp), $weekdayNames)) {
        if (! isHoliday($timestamp, $holidays)) {
            $weekdays[] = $timestamp;
        }
    }
}

/* Display the list of non-holiday weekdays */
foreach ($weekdays as $weekday) {
    $output .= "\n<br>" . strftime("%A %c", $weekday);
}

return $output;