PHP get same day of same week next year - php

I'm working on a client scheduler and my employer wants it to automatically reschedule clients each year. He wants them to keep the same day of the same week every year.
For example, a client is scheduled for May 23rd 2014. This is the fourth friday of may. Once May 23rd 2014 has passed, a appointment for the fourth friday of may in 2015 should be booked (in this case the 22nd).
I've tried various things to get this to work (such as using DateTime to advance by a year and find "previous" of whatever day of the week it was). But every model I've tried breaks down a bit after just a few years. They'll end up on like...the second Friday of the month.
Does anyone have a way to get this to work? My employer is very specific about wanting the scheduler to work this way. x.x I'd really appreciate the help if someone knows how.
Thanks for reading this!

As has already been pointed out, there may not be a 5th Friday in June, for example, so there needs to be some standard way to decide which week next year is the same week as the current one.
As it happens there is already a standard for week numbering in ISO 8601 and PHP's DateTime class has built in functionality for handling them.
My suggestion would be to schedule the next meeting for the same day in the same ISO 8601 week number the following year. The following function will do that for you:-
/**
* #param \DateTime $date Date of the original meeting
* #return \DateTime Date of the next meeting
*/
function getSameDayNextYear(\DateTime $date = null)
{
if(!$date){
$date = new \DateTime();
}
return (new \DateTime())->setISODate((int)$date->format('o') + 1, (int)$date->format('W'), (int)$date->format('N'));
}
See it working with some test code.
I'm sure you'll agree that this is the simplest way of doing it and it should see you right for the next 100 years or more :)
References DateTime and Date for formats.

I think this will do what you need. You'll need to thoroughly test it out to be sure, though.
$event = new DateTime('2014-05-18');
$dayOfWeek = $event->format('l');
if ($dayOfWeek !== 'Sunday') {
$event->modify('previous Sunday');
}
else {
$event->modify('-1 day');
}
$event->modify('+1 year');
if ($dayOfWeek !== 'Sunday' && $dayOfWeek !== $event->format('l')) {
$event->modify('next ' . $dayOfWeek);
}
echo $event->format('Y-m-d');
Demo

So changing your requirements to "add a year and find the next matching day of the week" I've come up with this:
function nextDate($date = false){
if(!$date){ $date = new DateTime(); }
$oneYear = new DateInterval('P1Y');
$dayOfWeek = $date->format('w');
$nextDate = clone $date;
$nextDate->add($oneYear);
$nextYearDayOfWeek = $nextDate->format('w');
while($nextYearDayOfWeek != $dayOfWeek){
// add a day and check again
$nextDate->add(new DateInterval('P1D'));
$nextYearDayOfWeek = $nextDate->format('w');
}
return $nextDate;
}
And my tests:
$test1 = new DateTime('5/23/2014');
$test2 = new DateTime('5/24/2014');
$test3 = new DateTime('5/25/2014');
$test4 = new DateTime('5/26/2014');
$test5 = new DateTime('5/27/2014');
$test6 = new DateTime('5/28/2014');
$test7 = new DateTime('5/29/2014');
$test8 = new DateTime('1/1/2014');
$test9 = new DateTime('12/31/2014');
$test10 = new DateTime('5/5/2040');
$nextDate1 = nextDate($test1);
$nextDate2 = nextDate($test2);
$nextDate3 = nextDate($test3);
$nextDate4 = nextDate($test4);
$nextDate5 = nextDate($test5);
$nextDate6 = nextDate($test6);
$nextDate7 = nextDate($test7);
$nextDate8 = nextDate($test8);
$nextDate9 = nextDate($test9);
$nextDate10 = nextDate($test10);
print($nextDate1->format('m/d/y'));
print('<br />');
print($nextDate2->format('m/d/y'));
print('<br />');
print($nextDate3->format('m/d/y'));
print('<br />');
print($nextDate4->format('m/d/y'));
print('<br />');
print($nextDate5->format('m/d/y'));
print('<br />');
print($nextDate6->format('m/d/y'));
print('<br />');
print($nextDate7->format('m/d/y'));
print('<br />');
print($nextDate8->format('m/d/y'));
print('<br />');
print($nextDate9->format('m/d/y'));
print('<br />');
print($nextDate10->format('m/d/y'));
Results:
05/29/15
05/30/15
05/31/15
06/01/15
06/02/15
06/03/15
06/04/15
01/07/15
01/06/16
05/11/41
Edit
I've modified the function below to find the closest day of the week instead of the next one (though it tends to just be the same as the previous one except subtracting).
function nextDate($date = false){
if(!$date){ $date = new DateTime(); }
$oneYear = new DateInterval('P1Y');
$dayOfWeek = $date->format('w');
$nextDate = clone $date;
$nextDate->add($oneYear);
$nextYearDayOfWeek = $nextDate->format('w');
$diff = $dayOfWeek-$nextYearDayOfWeek;
// if $diff is more than 3, it's faster to go the other way
if(abs($diff) > 3){
if($diff > 0){
$diff = $diff-7;
}else{
$diff = 7+$diff;
}
}
if($diff != 0){
if($diff < 0){
$nextDate->sub(new DateInterval('P'.abs($diff).'D'));
}else{
$nextDate->add(new DateInterval('P'.$diff.'D'));
}
}
return $nextDate;
}
Test results this time:
05/22/15
05/23/15
05/24/15
05/25/15
05/26/15
05/27/15
05/28/15
12/31/14
12/30/15
05/04/41

Related

Carbon: Get start and end date of week when knowing week in year and year

Carbon provides the function weekOfYear to get the week of the year as integer. However I need to go the other way round to get the a date based on the year + the week of the year.
Carbon::now()->weekOfYear(); // todays week of the year
E.g.
year: 2016
week of year: 42
As a result i need the start and end date of this given week. However i cannot find a fitting function in the Carbon docs
Carbon is a wrapper for PHP's DateTime, so you can use setISODate:
$date = Carbon::now(); // or $date = new Carbon();
$date->setISODate(2016,42); // 2016-10-17 23:59:59.000000
echo $date->startOfWeek(); // 2016-10-17 00:00:00.000000
echo $date->endOfWeek(); // 2016-10-23 23:59:59.000000
/**
* #return array{0: \DateTime, 1: \DateTime}
*/
public static function getWeekDates(\DateTimeInterface $selectedDate): array
{
$daysFromMonday = (int) $selectedDate->format('N') - 1;
$fromDate = \DateTimeImmutable::createFromInterface($selectedDate)->modify("-{$daysFromMonday} days");
$toDate = $fromDate->modify('+6 days');
return [
\DateTime::createFromImmutable($fromDate),
\DateTime::createFromImmutable($toDate),
];
}
This returns date of Monday and Sunday (iso week number).
If you wish to know dates of Sunday and Saturday, you can easily modify the function (replace 'N' with 'w' in format) and remove -1
$WeekArray = array();
$FirstDate = Carbon::now()->addYears(-2);
$LastDate = Carbon::now()->addYears(2);
while ($FirstDate <= $LastDate) {
$WeekNumber = Carbon::parse($FirstDate)->weekOfYear;
$WeekYear = Carbon::parse($FirstDate)->year;
$StartOfWeek = Carbon::parse($FirstDate)->startOfWeek();
$EndOfWeek = Carbon::parse($FirstDate)->endOfWeek();
$WeekItem = new stdClass;
$WeekItem->WeekNumber = $WeekNumber;
$WeekItem->WeekYear = $WeekYear;
$WeekItem->FirstDate = AppHelper::_DateFormatMysql($StartOfWeek);
$WeekItem->LastDate = AppHelper::_DateFormatMysql($EndOfWeek);
if (count($WeekArray) > 0) {
if (collect($WeekArray)->where('WeekYear', $WeekItem->WeekYear)->where('WeekNumber', $WeekItem->WeekNumber)
->where('FirstDate', $WeekItem->FirstDate)->where('LastDate', $WeekItem->LastDate)->count() == 0)
{
array_push($WeekArray, $WeekItem);
}
}
else {
array_push($WeekArray, $WeekItem);
}
$FirstDate = Carbon::parse($FirstDate)->addDays(1);
}

Php: How can I get the same date of the following months, quarterly and semi-annually

I'm this situation where users can choose to be billed either every month, quarter or semi-annual on one specific date the choose in a billing cycle. I'm using Laravel PHP framework.
Eg. Monthly - 5 May 2016, 5 June 2016, 5 July 2016, etc.
Billed on 5 on every month
Eg. Quarterly - 10 Jan 2016, 10 March 2016, 10 June 2016 etc...
Billed on 10 after every three months
Eg. Semi-Annually - 13 Apr 2016, 13 Sept 016
Billed on 13 after every six months.
The goal here is to get the same date on the every month the user choose to be billed, but in a month, quarterly or semi-annually.
This is my code after I play with #Rishi methode for some time
public function as_you_go($pay_as_you_go,$grand_total,$payment_date,$policy_id)
{
$policy = $this->findorFail($policy_id);
if($pay_as_you_go == 'Semi-Annually'){
$payments_no = 2;
$installment_amount = $grand_total/$payments_no;
$month_gap = 6;
$add_month = '+6 month';
}elseif($pay_as_you_go == 'Quarterly'){
$payments_no = 4;
$installment_amount = $grand_total/$payments_no;
$month_gap = 3;
$add_month = '+3 month';
}elseif($pay_as_you_go == 'Monthly'){
$payments_no = 12;
$installment_amount = $grand_total/$payments_no;
$month_gap = 1;
$add_month = '+1 month';
}
// Pay as you go calculations
for ($x = 0; $x < $payments_no; $x++) {
//$add_month = '+'.$x.' month';
$installment = new \App\Installment;
$installment->amount = $installment_amount;
if(\App\Installment::wherePayableType('App\Policy')->wherePayableId($policy->id)->first()){
$payment = \App\Installment::wherePayableType('App\Policy')->wherePayableId($policy->id)->orderBy('id', 'desc')->first();
$date = $payment->payment_date->format('Y-m-d');
$installment->payment_date = date('Y-m-d',strtotime($date.$add_month));
}else{
$installment->payment_date = $payment_date;
}
$installment->is_payed = 'No';
$policy->installments()->save($installment);
}
}
This is my function I wanted to generates dates according to user's date of choice based on semi-annual, quarterly and monthly payment gap.
Try like this
<?php
$date = '1-may-2016';
echo date('d-F-Y',strtotime($date.'+1 month'))."\n";
echo date('d-F-Y',strtotime($date.'+3 month'))."\n";
echo date('d-F-Y',strtotime($date.'+6 month'))."\n";
?>
check output here : https://eval.in/582424
Also you need to think about dates like $date = '30-jan-2016';.
I'm not entirely sure what you are looking for, but I think the following will help you on your way.
You can use DateTime and DateInterval to manipulate dates to add on a number of months.
// We have a DateTime object which is on the 5th may
$date = new DateTime('2016-05-05');
$billingType = 'monthly';
switch ($billingType) {
case 'monthly':
$interval = new DateInterval('P1M');
break;
case 'quarterly':
$interval = new DateInterval('P3M');
break;
case 'biannually':
$interval = new DateInterval('P6M');
break;
}
$newDate = clone $date;
$newDate->add($interval);
echo $date->format('Y-m-d'); // 2016-05-05
echo $newDate->format('Y-m-d'); // 2016-06-05
Let's say that you wanted to check if today is the day to bill someone...
function isBillingDate(DateTime $date, DateTime $billingDate, $billingType)
{
switch ($billingType) {
case 'monthly':
$interval = new DateInterval('P1M');
break;
case 'quarterly':
$interval = new DateInterval('P3M');
break;
case 'biannually':
$interval = new DateInterval('P6M');
break;
}
$isBillingDate = false;
$date->setTime(00, 00, 00);
$billingDate->setTime(00, 00, 00);
do {
if ($date == $billingDate) {
$isBillingDate = true;
} else {
$billingDate->add($interval);
}
} while ($isBillingDate === false && $date <= $billingDate);
return $isBillingDate;
}
$date = new DateTime('now'); // We want to check if we should bill them today (3rd June)
$billingStartDate = new DateTime('2016-05-03'); // They signed up to get billed on the 3rd of May
$billingType = 'monthly'; // They want to get billed every month
var_dump(isBillingDate($date, $billingStartDate, $billingType)); // True
$billingStartDate = new DateTime('2016-03-03'); // They signed up to get billed on the 3rd of March
$billingType = 'quarterly'; // They want to get billed quarterly
var_dump(isBillingDate($date, $billingStartDate, $billingType)); // True
$billingStartDate = new DateTime('2016-04-03'); // They signed up to get billed on the 3rd of April
$billingType = 'quarterly'; // They want to get billed quarterly
var_dump(isBillingDate($date, $billingStartDate, $billingType)); // False
Based on the code from Rishi I made this.
It splits the date to two parts and uses one to the month calculation and the other to the day.
Edit: noticed a quite obvious error in the code.
<?php
$date = '2016-01-26';
$date2= substr($date,0,7)."-01";
$period = "+3 month";
If(substr($date,-2) > date('t',strtotime($date2.$period))){
echo date('t-F-Y',strtotime($date2.$period))."\n";
}else{
echo date("d-", strtotime($date)) . date('F-Y',strtotime($date2.$period))."\n";
}
?>
https://eval.in/582564
Output:
From 31 of january:
28-February-2016
30-April-2016
31-July-2016
function iterateMonths(DateTime $date, $months = 1, $iterations = 12)
{
$day = $date->format('d');
for ($a = 0; $a < $iterations; $a++)
{
// Increment at least one month, but cap at the last day
$date->modify("last day of next month");
// Add on additional months if required
if ($months > 1)
{
$mDiff = $months-1;
$date->modify("+{$mDiff} months");
}
// If we are billing earlier than the last day of the month,
// rewind that number of days
if ($day < $date->format('d'))
{
$dDiff = $date->format('d') - $day;
$date->modify("-{$dDiff} days");
}
echo $date->format('Y-m-d'), PHP_EOL;
}
}
Standard monthly billing
$date = new \DateTime('2016-06-03');
iterateMonths($date);
// 2016-07-03, 2016-08-03, 2016-09-03, etc
Late days in months
$date = new \DateTime('2016-01-31');
iterateMonths($date, 1, 11);
// 2016-02-29, 2016-03-31, 2016-04-30, 2016-05-31
Quarterly (for four quarters)
$date = new \DateTime('2016-07-14');
iterateMonths($date, 3, 4);
// 2016-10-14, 2017-01-14, 2017-04-14, 2017-07-14

last year, this year, next year with php DateTime

I am trying to create a dropbox that will display the last year, the current year and the next year using the php DateTime object.
In my current code I create three objects and have to call a method on 2 of them. This seems a bit heavy on the resources.
$today = new DateTime();
$last_year=new DateTime();
$last_year->sub(new DateInterval('P1Y'));
$next_year = new DateTime();
$next_year->add(new DateInterval('P1Y'));
echo date_format($last_year, 'Y').' '.date_format($today, 'Y').' '.date_format($next_year, 'Y');
another way I found to only use 1 object is
$today = new DateTime();
echo date_format($today->sub(new DateInterval('P1Y')), 'Y').' '.date_format($today->add(new DateInterval('P1Y')), 'Y').' '.date_format($today->add(new DateInterval('P1Y')), 'Y');
but that will become very confusing.
Can someone tell me a better way to do this using DateTime()? As I will need something similar for months ?
Depending upon your version of PHP (>= 5.4), you could tidy it up a bit like this:-
$today = new DateTime();
$last_year=(new DateTime())->sub(new DateInterval('P1Y'));
$next_year = (new DateTime())->add(new DateInterval('P1Y'));
echo $last_year->format('Y').' '.$today->format('Y').' '.$next_year->format('Y');
See it working.
A more readable and concise option may be to use \DateTimeImmutable.
$today = new DateTimeImmutable();
$one_year = new DateInterval('P1Y');
$last_year = $today->sub($one_year);
$next_year = $today->add($one_year);
echo $last_year->format('Y').' '.$today->format('Y').' '.$next_year->format('Y');
See it working.
Other than that, this all looks fine. Worry about optimisation when it is needed.
Try this. This quite efficient.
echo date("Y");
echo date("Y",strtotime("-1 year"));
echo date("Y",strtotime("+1 year"))
May be you can also limit the call of new DateInterval('P1Y') by creating one object and using it for all three calculations?
$interval = new DateInterval('P1Y');
$dateTime = new DateTime();
$lastYear = $dateTime->sub($interval)->format('Y');
$dateTime = new DateTime();
$nextYear = $dateTime->add($interval)->format('Y');
$dateTime = new DateTime();
$thisYear = $dateTime->format('Y');
echo $lastYear . ' ' . $thisYear . ' ' . $nextYear;
and by breaking the single string into multiple commands always helps me in reducing confusions.
<?php
$d = new DateTime('now');
$cy = $d->format('Y');
// Get previous year
$d->modify('-1 year');
$py = $d->format('Y');
//Next year : Since object has previous year, so +2 to get next year
$d->modify('+2 year');
$ny = $d->format('Y');
echo "Previous Year: ".$py."<br>";
echo "Current Year : ".$cy."<br>";
echo "Next Year : ".$ny."<br>";
$d = new DateTime('now');
$cm = $d->format('m');
$d->modify('-1 month');
$pm = $d->format('m');
$d->modify('+2 month');
$nm = $d->format('m');
echo "Previous Month: ".$pm."<br>";
echo "Current Month : ".$cm."<br>";
echo "Next Month : ".$nm."<br>";
?>
Output
Previous Year: 2013
Current Year : 2014
Next Year : 2015
Previous Month: 12
Current Month : 01
Next Month : 02
Just use basic math:
$current = date('Y');
$prev = $current - 1;
$next = $current + 1;
after reading all the answers I came up with this function to create a dropdown box for year.
$name is the name of the
$year_number is the number of years you want to display
this function starts with one year before the current year but you can easily modify it to start displaying from earlier years.
function drop_down_box_date_year(&$dbconn, $name, $year_number){
$today = new DateTime();
$interval = new DateInterval('P1Y');
$startyear = (new DateTime())->sub($interval);
echo '<select name="'.$name.'_year">';
for($i=0;$i<$year_number;$i++){
if($startyear->format('Y')==$today->format('Y')){
echo '<option value="'.$startyear->format('Y').'" selected>'.$startyear->format('Y').'</option>';
}else{
echo '<option value="'.$startyear->format('Y').'">'.$startyear->format('Y').'</option>';
}
$startyear->add($interval);
}
echo'</select>';
}

Getting date/time difference in PHP

Am trying to get the time difference between two days. But for certain date/time, I get wrong answers
Here is my code:
/****************************************
$start_date = new DateTime('23:58:40'); *These two still give
$end_date = new DateTime('00:00:00'); *a wrong answer
*****************************************/
$start_date = new DateTime('23:58:40');
$end_date = new DateTime('00:11:36');
$dd = date_diff($end_date, $start_date);
//Giving a wrong answer: Hours = 23, Minutes = 47, Seconds = 4
echo "Hours = $dd->h, Minutes = $dd->i, Seconds = $dd->s";
The awnser is correct. You provide two times. Without a date there is no way to know the last date is actually the next day. Just because you named the variable "end_date" doesnt mean PHP knows what you mean.
Perhaps you should include the date aswell in your request like
$start_date = new DateTime('2012-12-07 23:58:40');
$end_date = new DateTime('2012-12-08 00:11:36');
If you realy want to work with just times:
function differenceInTimes($start, $end) {
if (strtotime($start)>strtotime($end)) {
//start date is later then end date
//end date is next day
$s = new DateTime('2000-01-01 '.$start);
$e = new DateTime('2000-01-02 '.$end);
} else {
//start date is earlier then end date
//same day
$s = new DateTime('2000-01-01 '.$start);
$e = new DateTime('2000-01-01 '.$end);
}
return date_diff($s, $e);
}
$start_date = '23:58:40';
$end_date = '00:11:36';
$dd = differenceInTimes($start_date, $end_date);
echo "Hours = $dd->h, Minutes = $dd->i, Seconds = $dd->s";
//Hours = 0, Minutes = 12, Seconds = 56
Swap the arguments to date_diff
$dd = date_diff($start_date, $end_date);
Edit
After actually testing this theory it proved to be totally useless, giving the same answer.

Next business day of given date in PHP

Does anyone have a PHP snippet to calculate the next business day for a given date?
How does, for example, YYYY-MM-DD need to be converted to find out the next business day?
Example:
For 03.04.2011 (DD-MM-YYYY) the next business day is 04.04.2011.
For 08.04.2011 the next business day is 11.04.2011.
This is the variable containing the date I need to know the next business day for
$cubeTime['time'];
Variable contains: 2011-04-01
result of the snippet should be: 2011-04-04
Next Weekday
This finds the next weekday from a specific date (not including Saturday or Sunday):
echo date('Y-m-d', strtotime('2011-04-05 +1 Weekday'));
You could also do it with a date variable of course:
$myDate = '2011-04-05';
echo date('Y-m-d', strtotime($myDate . ' +1 Weekday'));
UPDATE: Or, if you have access to PHP's DateTime class (very likely):
$date = new DateTime('2018-01-27');
$date->modify('+7 weekday');
echo $date->format('Y-m-d');
Want to Skip Holidays?:
Although the original poster mentioned "I don't need to consider holidays", if you DO happen to want to ignore holidays, just remember - "Holidays" is just an array of whatever dates you don't want to include and differs by country, region, company, person...etc.
Simply put the above code into a function that excludes/loops past the dates you don't want included. Something like this:
$tmpDate = '2015-06-22';
$holidays = ['2015-07-04', '2015-10-31', '2015-12-25'];
$i = 1;
$nextBusinessDay = date('Y-m-d', strtotime($tmpDate . ' +' . $i . ' Weekday'));
while (in_array($nextBusinessDay, $holidays)) {
$i++;
$nextBusinessDay = date('Y-m-d', strtotime($tmpDate . ' +' . $i . ' Weekday'));
}
I'm sure the above code can be simplified or shortened if you want. I tried to write it in an easy-to-understand way.
For UK holidays you can use
https://www.gov.uk/bank-holidays#england-and-wales
The ICS format data is easy to parse. My suggestion is...
# $date must be in YYYY-MM-DD format
# You can pass in either an array of holidays in YYYYMMDD format
# OR a URL for a .ics file containing holidays
# this defaults to the UK government holiday data for England and Wales
function addBusinessDays($date,$numDays=1,$holidays='') {
if ($holidays==='') $holidays = 'https://www.gov.uk/bank-holidays/england-and-wales.ics';
if (!is_array($holidays)) {
$ch = curl_init($holidays);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
$ics = curl_exec($ch);
curl_close($ch);
$ics = explode("\n",$ics);
$ics = preg_grep('/^DTSTART;/',$ics);
$holidays = preg_replace('/^DTSTART;VALUE=DATE:(\\d{4})(\\d{2})(\\d{2}).*/s','$1-$2-$3',$ics);
}
$addDay = 0;
while ($numDays--) {
while (true) {
$addDay++;
$newDate = date('Y-m-d', strtotime("$date +$addDay Days"));
$newDayOfWeek = date('w', strtotime($newDate));
if ( $newDayOfWeek>0 && $newDayOfWeek<6 && !in_array($newDate,$holidays)) break;
}
}
return $newDate;
}
function next_business_day($date) {
$add_day = 0;
do {
$add_day++;
$new_date = date('Y-m-d', strtotime("$date +$add_day Days"));
$new_day_of_week = date('w', strtotime($new_date));
} while($new_day_of_week == 6 || $new_day_of_week == 0);
return $new_date;
}
This function should ignore weekends (6 = Saturday and 0 = Sunday).
This function will calculate the business day in the future or past. Arguments are number of days, forward (1) or backwards(0), and a date. If no date is supplied todays date will be used:
// returned $date Y/m/d
function work_days_from_date($days, $forward, $date=NULL)
{
if(!$date)
{
$date = date('Y-m-d'); // if no date given, use todays date
}
while ($days != 0)
{
$forward == 1 ? $day = strtotime($date.' +1 day') : $day = strtotime($date.' -1 day');
$date = date('Y-m-d',$day);
if( date('N', strtotime($date)) <= 5) // if it's a weekday
{
$days--;
}
}
return $date;
}
What you need to do is:
Convert the provided date into a timestamp.
Use this along with the or w or N formatters for PHP's date command to tell you what day of the week it is.
If it isn't a "business day", you can then increment the timestamp by a day (86400 seconds) and check again until you hit a business day.
N.B.: For this is really work, you'd also need to exclude any bank or public holidays, etc.
I stumbled apon this thread when I was working on a Danish website where I needed to code a "Next day delivery" PHP script.
Here is what I came up with (This will display the name of the next working day in Danish, and the next working + 1 if current time is more than a given limit)
$day["Mon"] = "Mandag";
$day["Tue"] = "Tirsdag";
$day["Wed"] = "Onsdag";
$day["Thu"] = "Torsdag";
$day["Fri"] = "Fredag";
$day["Sat"] = "Lørdag";
$day["Sun"] = "Søndag";
date_default_timezone_set('Europe/Copenhagen');
$date = date('l');
$checkTime = '1400';
$date2 = date(strtotime($date.' +1 Weekday'));
if( date( 'Hi' ) >= $checkTime) {
$date2 = date(strtotime($date.' +2 Weekday'));
}
if (date('l') == 'Saturday'){
$date2 = date(strtotime($date.' +2 Weekday'));
}
if (date('l') == 'Sunday') {
$date2 = date(strtotime($date.' +2 Weekday'));
}
echo '<p>Næste levering: <span>'.$day[date("D", $date2)].'</span></p>';
As you can see in the sample code $checkTime is where I set the time limit which determines if the next day delivery will be +1 working day or +2 working days.
'1400' = 14:00 hours
I know that the if statements can be made more compressed, but I show my code for people to easily understand the way it works.
I hope someone out there can use this little snippet.
Here is the best way to get business days (Mon-Fri) in PHP.
function days()
{
$week=array();
$weekday=["Monday","Tuesday","Wednesday","Thursday","Friday"];
foreach ($weekday as $key => $value)
{
$sort=$value." this week";
$day=date('D', strtotime($sort));
$date=date('d', strtotime($sort));
$year=date('Y-m-d', strtotime($sort));
$weeks['day']= $day;
$weeks['date']= $date;
$weeks['year']= $year;
$week[]=$weeks;
}
return $week;
}
Hope this will help you guys.
Thanks,.
See the example below:
$startDate = new DateTime( '2013-04-01' ); //intialize start date
$endDate = new DateTime( '2013-04-30' ); //initialize end date
$holiday = array('2013-04-11','2013-04-25'); //this is assumed list of holiday
$interval = new DateInterval('P1D'); // set the interval as 1 day
$daterange = new DatePeriod($startDate, $interval ,$endDate);
foreach($daterange as $date){
if($date->format("N") <6 AND !in_array($date->format("Y-m-d"),$holiday))
$result[] = $date->format("Y-m-d");
}
echo "<pre>";print_r($result);
For more info: http://goo.gl/YOsfPX
You could do something like this.
/**
* #param string $date
* #param DateTimeZone|null|null $DateTimeZone
* #return \NavigableDate\NavigableDateInterface
*/
function getNextBusinessDay(string $date, ? DateTimeZone $DateTimeZone = null):\NavigableDate\NavigableDateInterface
{
$Date = \NavigableDate\NavigableDateFacade::create($date, $DateTimeZone);
$NextDay = $Date->nextDay();
while(true)
{
$nextDayIndexInTheWeek = (int) $NextDay->format('N');
// check if the day is between Monday and Friday. In DateTime class php, Monday is 1 and Friday is 5
if ($nextDayIndexInTheWeek >= 1 && $nextDayIndexInTheWeek <= 5)
{
break;
}
$NextDay = $NextDay->nextDay();
}
return $NextDay;
}
$date = '2017-02-24';
$NextBussinessDay = getNextBusinessDay($date);
var_dump($NextBussinessDay->format('Y-m-d'));
Output:
string(10) "2017-02-27"
\NavigableDate\NavigableDateFacade::create($date, $DateTimeZone), is provided by php library available at https://packagist.org/packages/ishworkh/navigable-date. You need to first include this library in your project with composer or direct download.
I used below methods in PHP, strtotime() does not work specially in leap year February month.
public static function nextWorkingDay($date, $addDays = 1)
{
if (strlen(trim($date)) <= 10) {
$date = trim($date)." 09:00:00";
}
$date = new DateTime($date);
//Add days
$date->add(new DateInterval('P'.$addDays.'D'));
while ($date->format('N') >= 5)
{
$date->add(new DateInterval('P1D'));
}
return $date->format('Y-m-d H:i:s');
}
This solution for 5 working days (you can change if you required for 6 or 4 days working). if you want to exclude more days like holidays then just check another condition in while loop.
//
while ($date->format('N') >= 5 && !in_array($date->format('Y-m-d'), self::holidayArray()))

Categories