Related
I am new to PHP. I am displaying the monthly events which is starting event from 03/31/2021 on every month, so here is a critical situation come because not every month exists 31 date. So there is some php function available to check this date is exists in next coming months. If exists then display the event on that date otherwise display the last date of the month.
$monthly_counter = 0;
$monthly_counter_offset = 0;
$begin = new DateTime($val->start); // $val->start = '03/31/2021'
$end = new DateTime($val->repeat_end_date); // $val->repeat_end_date= '03/31/2022'
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($begin, $interval, $end);
foreach ($period as $dt)
{
$loop_date = $dt->format('m/d/Y');
$loop_date_formatted = $dt->format('Y-m-d');
$due_dates[] = $from_date_times;
$from_new_date_times = date('Y-m-d H:i', strtotime('+1 month', strtotime($from_date_times)));
$from_date_times = $from_new_date_times;
$deletedevents2=$val->deletedevents;
$arrayofdeleted=explode(",",$deletedevents2);
$originalDate = $from_date_times;
$newDateforcompare = date("m/d/Y", strtotime($originalDate));
if (in_array($loop_date_formatted, $arrayofdeleted))
{
continue;
}
$number_of_days = $val->number_of_days;
$end_new_date_times = date('Y-m-d H:i', strtotime('+'.$number_of_days.' day', strtotime($loop_date)));
if(date('Y-m-d ', strtotime($val->start))<date('Y-m-d', strtotime($val->ends)))
{
$end_new_date_times = date('Y-m-d H:i', strtotime('+1 day', strtotime($end_new_date_times)));
}
$skipcounter = $val->interval_value;
if (!empty($skipcounter) || $skipcounter != 1) {
$monthly_counter++;
$monthly_counter_offset++;
if ($monthly_counter == $skipcounter || $monthly_counter_offset == 1) {
$monthly_counter = 0;
} else {
continue;
}
} else {
}
$rows[] = array(
'id' => $val->id,
'title' => $val->title,
'description' => $val->calendar_comments,
'start' => $loop_date,
'end' => $end_new_date_times,
'borderColor'=>$val->color,
'backgroundColor'=>$val->color_bg,
'className'=>'timegridclass',
'allDay' => $allday,
);
}
Since you're using fullCalendar, you can simply specify an event which uses RRule to specify the recurrence, rather than using complex PHP code to try and generate it.
e.g.
events: [
{
title: "Sales Meeting",
rrule: "FREQ=MONTHLY;BYMONTHDAY=28,29,30,31;BYSETPOS=-1"
}
]
Working demo: https://codepen.io/ADyson82/pen/bGByBaV
This will generate an event which repeats on the last day of every month, regardless whether the month is 28, 29, 30 or 31 days long.
Obviously you can use PHP to generate this event object, and enhance it with a custom title, start/end dates etc as per your database contents. But I have shown you the basic approach.
Credit to this answer for the specific RRule string.
Documentation: https://fullcalendar.io/docs/rrule-plugin and https://github.com/jakubroztocil/rrule
I have to create a scheduling component that will plan e-mails that need to be sent out. Users can select a start time, end time, and frequency. Code should produce a random moment for every frequency, between start and end time. Outside of office hours.
Paramaters:
User can select a period between 01/01/2020 (the start) and 01/01/2021 (the end). In this case user selects a timespan of one exactly year.
User can select a frequency. In this case user selects '2 months'.
Function:
Code produces a list of datetimes. The total time (one year) is divided by frequency (2 months). We expect a list of 6 datetimes.
Every datetime is a random moment in said frequency (2 months). Within office hours.
Result:
An example result for these paramaters might as follows, with the calculated frequency bounds for clarity:
[jan/feb] 21-02-2020 11.36
[mrt/apr] 04-03-2020 16.11
[mei/jun] 13-05-2020 09.49
[jul-aug] 14-07-2020 15.25
[sep-okt] 02-09-2020 14.09
[nov-dec] 25-12-2020 13.55
--
I've been thinking about how to implement this best, but I can't figure out an elegant solution.
How could one do this using PHP?
Any insights, references, or code spikes would be greatly appreciated. I'm really stuck on this one.
I think you're just asking for suggestions on how to generate a list of repeating (2 weekly) dates with a random time between say 9am and 5pm? Is that right?
If so - something like this (untested, pseudo code) might be a starting point:
$start = new Datetime('1st January 2021');
$end = new Datetime('1st July 2021');
$day_start = 9;
$day_end = 17;
$date = $start;
$dates = [$date]; // Start date into array
while($date < $end) {
$new_date = clone($date->modify("+ 2 weeks"));
$new_date->setTime(mt_rand($day_start, $day_end), mt_rand(0, 59));
$dates[] = $new_date;
}
var_dump($dates);
Steve's anwser seems good, but you should consider 2 additional things
holiday check, in the while after first $new_date line, like:
$holiday = array('2021-01-01', '2021-01-06', '2021-12-25');
if (!in_array($new_date,$holiday))
also a check if date is a office day or a weekend in a similar way as above with working days as an array.
It's kind of crappy code but I think it will work as you wish.
function getDiffInSeconds(\DateTime $start, \DateTime $end) : int
{
$startTimestamp = $start->getTimestamp();
$endTimestamp = $end->getTimestamp();
return $endTimestamp - $startTimestamp;
}
function getShiftData(\DateTime $start, \DateTime $end) : array
{
$shiftStartHour = \DateTime::createFromFormat('H:i:s', $start->format('H:i:s'));
$shiftEndHour = \DateTime::createFromFormat('H:i:s', $end->format('H:i:s'));
$shiftInSeconds = intval($shiftEndHour->getTimestamp() - $shiftStartHour->getTimestamp());
return [
$shiftStartHour,
$shiftEndHour,
$shiftInSeconds,
];
}
function dayIsWeekendOrHoliday(\DateTime $date, array $holidays = []) : bool
{
$weekendDayIndexes = [
0 => 'Sunday',
6 => 'Saturday',
];
$dayOfWeek = $date->format('w');
if (empty($holidays)) {
$dayIsWeekendOrHoliday = isset($weekendDayIndexes[$dayOfWeek]);
} else {
$dayMonthDate = $date->format('d/m');
$dayMonthYearDate = $date->format('d/m/Y');
$dayIsWeekendOrHoliday = (isset($weekendDayIndexes[$dayOfWeek]) || isset($holidays[$dayMonthDate]) || isset($holidays[$dayMonthYearDate]));
}
return $dayIsWeekendOrHoliday;
}
function getScheduleDates(\DateTime $start, \DateTime $end, int $frequencyInSeconds) : array
{
if ($frequencyInSeconds < (24 * 60 * 60)) {
throw new \InvalidArgumentException('Frequency must be bigger than one day');
}
$diffInSeconds = getDiffInSeconds($start, $end);
// If difference between $start and $end is bigger than two days
if ($diffInSeconds > (2 * 24 * 60 * 60)) {
// If difference is bigger than 2 days we add 1 day to start and subtract 1 day from end
$start->modify('+1 day');
$end->modify('-1 day');
// Getting new $diffInSeconds after $start and $end changes
$diffInSeconds = getDiffInSeconds($start, $end);
}
if ($frequencyInSeconds > $diffInSeconds) {
throw new \InvalidArgumentException('Frequency is bigger than difference between dates');
}
$holidays = [
'01/01' => 'New Year',
'18/04/2020' => 'Easter 1st official holiday because 19/04/2020',
'20/04/2020' => 'Easter',
'21/04/2020' => 'Easter 2nd day',
'27/04' => 'Konings',
'04/05' => '4mei',
'05/05' => '4mei',
'24/12' => 'Christmas 1st day',
'25/12' => 'Christmas 2nd day',
'26/12' => 'Christmas 3nd day',
'27/12' => 'Christmas 3rd day',
'31/12' => 'Old Year'
];
[$shiftStartHour, $shiftEndHour, $shiftInSeconds] = getShiftData($start, $end);
$amountOfNotifications = floor($diffInSeconds / $frequencyInSeconds);
$periodInSeconds = intval($diffInSeconds / $amountOfNotifications);
$maxDaysBetweenNotifications = intval($periodInSeconds / (24 * 60 * 60));
// If $maxDaysBetweenNotifications is equals to 1 then we have to change $periodInSeconds to amount of seconds for one day
if ($maxDaysBetweenNotifications === 1) {
$periodInSeconds = (24 * 60 * 60);
}
$dates = [];
for ($i = 0; $i < $amountOfNotifications; $i++) {
$periodStart = clone $start;
$periodStart->setTimestamp($start->getTimestamp() + ($i * $periodInSeconds));
$seconds = mt_rand(0, $shiftInSeconds);
// If $maxDaysBetweenNotifications is equals to 1 then we have to check only one day without loop through the dates
if ($maxDaysBetweenNotifications === 1) {
$interval = new \DateInterval('P' . $maxDaysBetweenNotifications . 'DT' . $seconds . 'S');
$date = clone $periodStart;
$date->add($interval);
$dayIsWeekendOrHoliday = dayIsWeekendOrHoliday($date, $holidays);
} else {
// When $maxDaysBetweenNotifications we have to loop through the dates to pick them
$loopsCount = 0;
$maxLoops = 3; // Max loops before breaking and skipping the period
do {
$day = mt_rand(0, $maxDaysBetweenNotifications);
$periodStart->modify($shiftStartHour);
$interval = new \DateInterval('P' . $day . 'DT' . $seconds . 'S');
$date = clone $periodStart;
$date->add($interval);
$dayIsWeekendOrHoliday = dayIsWeekendOrHoliday($date, $holidays);
// If the day is weekend or holiday then we have to increment $loopsCount by 1 for each loop
if ($dayIsWeekendOrHoliday === true) {
$loopsCount++;
// If $loopsCount is equals to $maxLoops then we have to break the loop
if ($loopsCount === $maxLoops) {
break;
}
}
} while ($dayIsWeekendOrHoliday);
}
// Adds the date to $dates only if the day is not a weekend day and holiday
if ($dayIsWeekendOrHoliday === false) {
$dates[] = $date;
}
}
return $dates;
}
$start = new \DateTime('2020-12-30 08:00:00', new \DateTimeZone('Europe/Sofia'));
$end = new \DateTime('2021-01-18 17:00:00', new \DateTimeZone('Europe/Sofia'));
$frequencyInSeconds = 86400; // 1 day
$dates = getScheduleDates($start, $end, $frequencyInSeconds);
var_dump($dates);
You have to pass $start, $end and $frequencyInSeconds as I showed in example and then you will get your random dates. Notice that I $start and $end must have hours in them because they are used as start and end hours for shifts. Because the rule is to return a date within a shift time only in working days. Also you have to provide frequency in seconds - you can calculate them outside the function or you can change it to calculate them inside. I did it this way because I don't know what are your predefined periods.
This function returns an array of \DateTime() instances so you can do whatever you want with them.
UPDATE 08/01/2020:
Holidays now are part of calculation and they will be excluded from returned dates if they are passed when you are calling the function. You can pass them in d/m and d/m/Y formats because of holidays like Easter and in case when the holiday is on weekend but people will get additional dayoff during the working week.
UPDATE 13/01/2020:
I've made updated code version to fix the issue with infinite loops when $frequencyInSeconds is shorter like 1 day. The new code used few functions getDiffInSeconds, getShiftData and dayIsWeekendOrHoliday as helper methods to reduce code duplication and cleaner and more readable code
I have a php code as shown below in which on the 1st day of every month, I am copying 2nd JSON object array (next_month) content into 1st JSON object array (current_month).
In the 2nd JSON object array (next_month), I want to have next month dates. That will also happen on the 1st day of every month. Currently I am storing nada. Let us suppose that today is 1st day of November.
php code:
$value = json_decode(file_get_contents('../hyt/dates.json'));
if ((date('j') == 1)) {
$month = 11;
$year = date('Y');
$current_month_days = (date('t', strtotime($year . '-' . $month . '-01')));
$next_month_days = (date('t', strtotime($year . '-' . ($month + 1) . '-01')));
$value->current_month = $value->next_month; // Line Y
$value->next_month = array_fill(0, ($next_month_days), nada); // Line Z
}
The current look of JSON (dates.json) is shown below:
{"current_month": ["2020-10-01", "2020-10-02", "2020-10-03", "2020-10-04", "2020-10-05", "2020-10-06", "2020-10-07", "2020-10-08", "2020-10-09", "2020-10-10", "2020-10-10", "2020-10-12", "2020-10-13", "2020-10-14", "2020-10-15", "2020-10-16", "2020-10-17", "2020-10-18", "2020-10-19", "2020-10-20", "2020-10-21", "2020-10-22", "2020-10-23", "2020-10-24", "2020-10-25", "2020-10-26", "2020-10-27", "2020-10-28", "2020-10-29", "2020-10-30","2020-10-31"],
"next_month": ["2020-11-01", "2020-11-02", "2020-11-03", "2020-11-04", "2020-11-05", "2020-11-06", "2020-11-07", "2020-11-08", "2020-11-09", "2020-11-11", "2020-11-11", "2020-11-12", "2020-11-13", "2020-11-14", "2020-11-15", "2020-11-16", "2020-11-17", "2020-11-18", "2020-11-19", "2020-11-20", "2020-11-21", "2020-11-22", "2020-11-23", "2020-11-24", "2020-11-25", "2020-11-26", "2020-11-27", "2020-11-28", "2020-11-29", "2020-11-30"] }
Problem Statement:
I am wondering what changes I should make at Line Z so that in the second JSON object array, I am able to get next month dates. At present, I am storing nada.
The content which I want in the JSON on the 1st day of November month after successful execution of Line Y and Line Z is:
{"current_month": ["2020-11-01", "2020-11-02", "2020-11-03", "2020-11-04", "2020-11-05", "2020-11-06", "2020-11-07", "2020-11-08", "2020-11-09", "2020-11-11", "2020-11-11", "2020-11-12", "2020-11-13", "2020-11-14", "2020-11-15", "2020-11-16", "2020-11-17", "2020-11-18", "2020-11-19", "2020-11-20", "2020-11-21", "2020-11-22", "2020-11-23", "2020-11-24", "2020-11-25", "2020-11-26", "2020-11-27", "2020-11-28", "2020-11-29", "2020-11-30"],
"next_month": ["2020-12-01", "2020-12-02", "2020-12-03", "2020-12-04", "2020-12-05", "2020-12-06", "2020-12-07", "2020-12-08", "2020-12-09", "2020-12-11", "2020-12-11", "2020-12-12", "2020-12-13", "2020-12-14", "2020-12-15", "2020-12-16", "2020-12-17", "2020-12-18", "2020-12-19", "2020-12-20", "2020-12-21", "2020-12-22", "2020-12-23", "2020-12-24", "2020-12-25", "2020-12-26", "2020-12-27", "2020-12-28", "2020-12-29", "2020-12-30", "2020-12-31"] }
This is what I have tried:
This is what I have tried at Line Z but its storing only today's date in JSON object array.
$value->next_month = array_fill(0, ($next_month_days), date("Y-m-d")); // Line Z
I think you should completely recreate your JSON string. It starts on the first day of the current month. The loop always runs as long as the month remains. The whole thing then again for the following month.
$arr = $cur = [];
$date = date_create('first day of this month 00:00');
$startMonth = $month = $date->format('m');
while($startMonth == $month){
$cur[] = $date->format('Y-m-d');
$date->modify('+1 Day');
$month = $date->format('m');
}
$arr["current_month"] = $cur;
$startMonth = $month;
$cur = [];
while($startMonth == $month){
$cur[] = $date->format('Y-m-d');
$date->modify('+1 Day');
$month = $date->format('m');
}
$arr["next_month"] = $cur;
$jsonStr = json_encode($arr);
You are using array_fill, which is used to fill at least part of an array with the same value. I would recommend using a simple for loop:
$next_month_array = [];
$next_month = $month < 12 ? $month + 1 : 1;
$year = date('Y');
for($day_counter = 1; $day_counter <= $next_month_days; $day_counter++) {
$next_month_array[] = "$year-$next_month-$day_counter";
}
$value->next_month = $next_month_array;
I have a data like this:
$date = '01-01-2014';
$time = '15:20:00';
$location = 'New Delhi';
$recursive = '1';
.........................
......................... // other data
$recursive = 1 means weekly and 2 means monthly.
Now what i am tring to do is if recursive type is weekly then add 7 days into it till 3 months and if recursive type is monthly then add 1 month into it till 3 months.
Exa:1 $date = '01-01-2014' and $recursive = '1'
Means in above example $recursive is weekly, so get a recursive date for January, February and March.
So the expected results are:
01-01-2014, 08-01-2014, 15-01-2014, 22-01-2014, 29-01-2014 (recursiive date in january)
05-02-2014, 12-02-2014, 19-02-2014, 26-02-2014 (recursiive date in february)
05-03-2014, 12-03-2014, 19-03-2014, 26-03-2014 (recursiive date in march)
Exa 2: $date = 15-04-2014 and $recursive = 1 then get recursive date for April, May and June.
output:
15-04-2014,22-04-2014,29-04-2014 (recursive date in april)
06-05-2014,13-05-2014,20-05-2014,27-05-2014 (recursive date in may)
03-06-2014,10-06-2014,17-06-2014,24-06-2014 (recursive date in june)
Exa 3 : $date = 01-01-2014 and $recursive = 2 then get recursive date for April, May and June.
This is monthly recursive, means add 1 month into it.
output:
01-01-2014
01-02-2014 (recursiive date in february)
01-03-2014 (recursiive date in march)
then i want to insert these dates with other data into database table.
so how to achive above things? should i write logic in php or use mysql query for it?
Thanks in advance.
SIDENOTE: currently i am using this accepted answer. but now i am trying to change that.
so basically what you want to do is something like this.
//you have to have a default time zone set.. so i just did this you should already have it in your .ini file
date_default_timezone_set('America/Los_Angeles');
$date = '01-01-2014';
$time = '15:20:00';
$location = 'New Delhi';
$recursive = '1';
//set your start date and end date
$startdate = date_create($date);
$enddate = date_create($date);
$enddate = date_add($enddate,date_interval_create_from_date_string("3 months"));
//set the interval string
if($recursive == '1'){
$str = "7 days";
} else {
$str = "1 month";
}
function recursivefunc($str, $start, $end){
//if the start is equal or bigger than end pop out.
$s = date_format($start,"Y/m/d");
$e = date_format($end,"Y/m/d");
if(strtotime($s) >= strtotime($e)){
return 1;
}
echo date_format($start,"Y/m/d"), '<br>'; //print out the starting date for each loop
$newDate = date_add($start,date_interval_create_from_date_string($str)); //increment the start
recursiveFunc($str, $newDate, $end); //call the function again
}
recursiveFunc($str, $startdate, $enddate); // initial call to the function
This is how i solve it.
$date = '01-01-2014';
$location = 'New Delhi';
$start = strtotime("+2 months", strtotime($date)); //start date
$end_date = date("Y-m-t", $start); // last day of end month
$end = strtotime($end_date); //last date
/* if recursion type is weekly */
if($json['recurrence'] == "1")
{
for($dd=$start; $dd<=$end;)
{
$new_date = date('Y-m-d', $dd);
$data[] = array(
'date' => $new_date,
'location' => $location
);
$dd = strtotime("+7 day", $dd); // add 7 days
}
}
if($json['recurrence'] == "2")
{
for($dd=$start; $dd<=$end;)
{
$new_date = date('Y-m-d', $dd);
$data[] = array(
'date' => $new_date,
'location' => $location
);
$dd = strtotime("+1 month", $dd); //add 1 month
}
}
echo "<pre>";
print_r($data);
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()))