I have a website where we show next delivery date, eg for a weekly delivery each Tuesday -- although the actual day that deliveries go out needs to be manually changed sometimes. I need to update it to (eg) Tuesday and Friday deliveries, and I'm struggling to find a good method.
Here's how I've got it set up currently:
<?php
$start_date = '2020-05-05'; // Date in the past to start counting from: YYYY-MM-DD
$date_interval = new DateInterval('P7D'); // DELIVERY EVERY x DAYS: PxD (usually P7D)
// create a DateTime object that represents start of sequence
$start_datetime = DateTime::createFromFormat('Y-m-d', $start_date);
// create a DateTime object representing the current date
$current_datetime = new DateTime('today');
// determine end date for DatePeriod object that will later be used.
// This is no further out than current date plus the interval.
$end_datetime = new DateTime('tomorrow');
$end_datetime->add($date_interval);
$date_period = new DatePeriod($start_datetime, $date_interval, $end_datetime);
// iterate until the last date in the set
foreach($date_period as $dp) {
$next_delivery = $dp;
}
echo $next_delivery->format('l, M j, Y');
?>
The dateperiod class says that it accepts ISO 8601 time periods, but as far as I can tell there's no way to set it to "next Tuesday or Friday, whichever is closer".
One hacky method I've thought of that would work is to run this function twice, once for Tuesday and once for Friday, compare with today's date, and display whichever is sooner in the future. But surely there's a more elegant way?
It is not very difficult to find the next available Tuesday or Friday. It is the smaller date of both.
echo min(date_create('next Tuesday'),date_create('next Friday'))->format('l, M j, Y');
Alternatively with a PHP extension for DateTime API called dt. You can find it here.
This class supports date calculations with crontab expressions. The days of the week start with 0 for Sunday. If you want to calculate the next Tuesday or Friday at 14:00 as an example, you only have to do this:
$cron = "0 14 * * 2,5"; //next Tuesday or Friday 14:00
$next_delivery = dt::create('today')->nextCron($cron); //today is 2020-05-10
echo $next_delivery->format('l, M j, Y, H:i');
//Tuesday, May 12, 2020, 14:00