PHP Display next delivery date for twice weekly deliveries - php

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?

That's a very long winded way to find the next available Tuesday or Friday. One way to do it is check to see what day of the week it is and dynamically set the day based on that:
$day = (in_array((int) date('w'), [0,1,5,6], true)) ? 'Tuesday' : 'Friday';
echo (new DateTime("next {$day}"))->format('l, M j, Y');
output:
Tuesday, May 12, 2020
The code above checks to see if the day is Sunday, Monday, Friday, Or Saturday. If so, set the next day to "Tuesday". Otherwise, set it to "Friday". Then you can use a relative datetime value to set your date.
If you want a more human readable version of this you can spell out the days:
$day = (in_array(date('l'), ['Sunday', 'Monday', 'Friday', 'Saturday'], true)) ? 'Tuesday' : 'Friday';

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

Related

Get first day date of the week on a given date PHP

I have a date 2015-12-16
i want to get the date of the first day's date for the current week of my date
here 2015-12-16 is in the week 51 of the year then i want to get the first day's date of the week 51 ( 2015-12-14 here)
how could i do it ?
thank you
EDIT: it must work when there are 53 weeks in the year (like in 2015 for example)
You can do the following:
$dateTime = new DateTime("2015-12-16");
$weekNo = $dateTime->format("W");
$newDate = new DateTime();
$newDate->setISODate($dateTime->format("Y"), $weekNo);
Example:
http://sandbox.onlinephpfunctions.com/code/281a1ac298bfee8be421e333e4b7e92c6bb44d65
Since the above is a bit off in some cases here's something more reliable:
$dateTime = new DateTime("2016-01-01");
$dateTime->sub(new DateInterval("P".($dateTime->format("w")-1)."D")); //Since the weekdays are 1-based.
Example:
http://sandbox.onlinephpfunctions.com/code/c5cb0f077fa77974d977ddbffa6bc0b61f9d7851
$date = new \DateTime('2015-12-16');
echo $date->modify('last sunday +1 day')->format('Y-m-d');
This gets start of this week if you count monday to sunday.
Try this:
date('Y-m-d', strtotime('This week', strtotime('2015-12-16')));

PHP Carbon - Create a date in future relative to current time

Imagine we have the day (of week) and the time of an event ( that is in the future ) :
$day = "Wednesday";
$time = "13:00";
And we want to create a Carbon date for that, but it has to be relative to current time :
$carbon = new Carbon();
For example if $carbon is Tuesday, 2017-01-17 09:00,
the $event date that we create should be Wednesday, 2017-01-18 13:00
In other words, the $event is a date that is taking place in the next 7 days. We don't have it's year, month and other data, but we do know it's day of week and the time.
you should be able to use something like:
Carbon::parse('next ' . $day)
and you can also throw the $time part in there somewhere too but can't remember exactly how right now.

DateTime API only outputs DAY in the future? PHP

If I send a DAY and TIME (not DATE) to the DateTime API like this :
$tz = new \DateTimeZone("UTC");
$now = new \DateTime("now", $tz);
$then = \DateTime::createFromFormat('l g A', 'Thursday 8 PM', $tz);
And it is currently Saturday 26th March, $then, when echoed as follows :
echo $then->format('l jS, F');
Will return :
Thursday 31st, March
How do I make it return the date of the Thursday in the CURRENT week that has just passed :
Thursday 24th March
Not the next Thursday?
DateTime::__construct() and strtotime() uses a lot of rules to guess what you mean when you specify an incomplete or relative date. Most of the times thy guess right but some of the rules are very similar and the final result is not the one expected by the programmer.
DateTime::createFromFormat() is limited, it cannot understand all the formats from the list.
You try to parse a relative date format. When only the day name is specified, it is interpreted as the next occurrence of the specified day of the week (see the dayname entry under the Day-based Notations table in the documentation.)
You can get the date you want by using Thursday this week instead. DateTime::createFromFormat() doesn't understand relative dates that contain references to the week but DateTime::__construct() does.
Try this:
$then = new \DateTime('Thursday this week 8 PM', $tz);
Could always call the 'sub' method on it, subtracting 7 days.
$tz = new \DateTimeZone("UTC");
$now = new \DateTime("now", $tz);
$then = \DateTime::createFromFormat('l g A', 'Thursday 8 PM', $tz);
$then->sub(new DateInterval('P7D'));
echo $then->format('l jS, F');

How to calculate the dates of particular days in the same week number from last year?

I'm aware of the vast amount of date questions on SO but I am stumped at this one.
I need to run some reports and in order to do so I need to work out some dates.
The report will run on a Monday and I need to work out the dates of the Sunday the week before and the following Saturday.
e.g. The report will be run on Monday the 28th May and the dates I need are Sunday the 20th May and Saturday the 26th May.
I then need the same values but for the previous week, so Sunday the 13th May and Saturday the 19th May.
I think this part will be fine as it's just a case of getting the current date of the Monday when the report is run and and manipulating it from there.
THEN finally, the part I can't work out is the first week I mentioned, I need the corresponding dates from last year, so the dates of the Sunday and Saturday from the same week number in the previous year.
I know the date function can give you the week number but can't see how to work out the dates of the Sunday of that week and the previous Saturday based on that.
This is what I have, forgive the OTT variable names:
$today = date('Y/m/d');
// reports run on a Monday and use last Sunday and the following Saturday's date so get yesterday's date first
$yesterday = strtotime ('-1 day', strtotime($today));
$yesterday = date ('Y/m/d', $yesterday);
// start of week (last Sunday)
$start_of_last_week = strtotime ('-1 week', strtotime($yesterday));
$start_of_last_week = date ('Y/m/d', $start_of_last_week);
// end of last week (the following Saturday)
$end_of_last_week = strtotime ('+ 6 days', strtotime($start_of_last_week));
$end_of_last_week = date ('Y/m/d', $end_of_last_week;
// start of previous week
$start_of_previous_week = strtotime ('-1 week', strtotime($start_of_last_week));
$start_of_previous_week = date ('Y/m/d', $start_of_previous_week);
// end of previous week
$end_of_previous_week = strtotime ('+ 6 days', strtotime($start_of_previous_week));
$end_of_previous_week = date ('Y/m/d', previous;
// the start of the same week last year
$start_of_last_week_last_year = strtotime ('-1 year', strtotime($start_of_last_week ));
But the above isn't right so not sure what to do next.
Any help is much appreciated.
You can find out the date of the Monday of a particular year and week number like this
date( 'Y-m-d', strtotime( '2012W21' )); //2011-05-23
Compound Date Formats

DateTime modify string for first day of current year

im looking for the DateTime modify String for the first day of the year (now 1. January 2011). I tried the following:
<?php
$time = new DateTime();
// works as expected, the first day of the current month
$time->modify('first day of this month');
echo $time->format('c')."\n";
// this doesn't work. I also tried several other ways
$time->modify('first day of january');
echo $time->format('c')."\n";
>
I know there are other ways to retrieve the date, but I search an string for DateTime->modify() no other solution.
You should specify the year too, as you can see in this example:
"first day of January 2008"
from the official doc.
Update: It works on php version >= 5.3.6
On v5.5.6
echo date('Y-m-d', strtotime('first day of January this year'));
Result: 2013-01-01
To get the day of the week for the first of the year
or the first day of the month
<?php
//This is for a given month
$m="May";
// this id for this month
//$m=date('F');
//if you want the day of Sunday instead D use lower case l
echo date('D', strtotime('first day of January this year'));
echo "<br>". date("D", strtotime('first day of'. $m ));
?>
Result Wed For May with D
Result Wednesday with l
This work for me (PHP 5.6 - not tested on older version)... as we talk for DateTime object
//Get current datetime
$now = new DateTime();
$now->modify('first day of January this year');
echo $now->format('Y-m-d');
// Print (current year)-01-01
echo (new DateTime())->modify('first day of January this year')->format('Y-m-d');

Categories