Simulate "do not disturb" functionality in PHP - php

I want to check between two user-specified times everyday and not run some function call (i.e. "Do Not Disturb").
For example, a user set a "Do Not Disturb" time block between 10:00pm to 6:00am (next day).
FYI, no days/dates are being specified by the end-user, ONLY times. This will run consistently everyday, 7 days a week.
So between 10pm-6am (next day), any function call is ignored. This is what I've written up so far:
$now = time(); // or $now = strtotime('11:00pm'); to simulate time to test
$start = strtotime('10:00pm');
$end = strtotime('6:00am +1 day');
// alternative time block
//$start = strtotime('10:00am');
//$end = strtotime('11:00am');
//debug
//echo date('r', $now) . '<br>' . date('r', $start) . '<br>' . date('r', $end) . '<br><br>';
if($start > $now || $now > $end) {
echo 'disturb';
} else {
echo 'do not disturb';
}
But this doesn't seem to work, because once you reach midnight, it's a new day, but the $end variable is already a day ahead.
I tried putting it a day behind, but then the issue is that the value of $end ends up being lower than the value of $start, which isn't correct.
I also tried adding a day to the $now variable whenever the time reaches midnight, but the issue w/ that is, what if the $start and $end times are within the same day?
What am I missing here?

Apparently you're trying to build some kind of calendar functionality here.
If you use strtotime('10:00pm'); this will change to the timestamp of the next day after midnight.
So you need to give the variable a date
$start = strtotime('2015-02-26 10:00pm');
$end = strtotime('2015-02-27 6:00am');
Not sure how you store these time blocks, but ideally they would be stored in a database table.
If it's every day the same you could do:
$now = time(); // or $now = strtotime('11:00pm'); to simulate time to test
$start = strtotime('10:00pm');
$end = strtotime('6:00am'); // without the +1 day
if($start > $end) {
if($start > $now && $now > $end) {
echo 'disturb';
} else {
echo 'do not disturb';
}
}else{
if($now < $start || $now > $end) {
echo 'disturb';
} else {
echo 'do not disturb';
}
}

That's a nice question actually,
You can use the the relatively new object oriented way of dealing with times.
I'll link you some info as I don't have time to write an entire example
http://php.net/manual/en/datetime.diff.php
http://php.net/manual/en/class.datetime.php
http://php.net/manual/en/class.dateinterval.php
specifically from the docs :
<?php
$datetime1 = new DateTime('2009-10-11');
$datetime2 = new DateTime('2009-10-13');
$interval = $datetime1->diff($datetime2);
echo $interval->format('%R%a days');
?>
Hope it helps

I would convert to DateTime() objects instead. Then you won't get any issues with days ending.
// obviously you'll need to feed in the date as well so
// that might involve some refactoring
$now = new DateTime();
$start = new DateTime('2015-02-26 10:00');
$end = new DateTime('2015-02-27 06:00');
Now you can compare as before.
If you don't know the date and your users are only specifying time, you might need to add the date dynamically. These are just for example.
Edit: to cope with unknown days, you could dynamically generate after grabbing today:
$today = new DateTime();
$start = new DateTime($today->format('Y-m-d') . ' 10:00');
$end = new DateTime($today->format('Y-m-d') . ' 06:00');
$end->add(new DateInterval('P1D'));

Related

Converting hours to timestamps

To convert a date to timestamp, I usually do this- strtotime ("2018-05-17 05:04:34) but now, I want to convert just hours (without date) e.g. 02:00:00 to timestamp. How do I do this?
Why I need this is to compare if a certain time is greater than the hour specified. This is what I am doing:
$reported = strtotime("2018-05-17 05:04:34");
$respons = strtotime("2018-05-17 17:04:34);
$response_time = $respons - $reported;
I want to be to check if $response_time is greater than 1 hour.
There is DateTime::diff, which probably does what you need
https://secure.php.net/manual/de/datetime.diff.php
In your case that should be
$datetime1 = new DateTime("2018-05-17 05:04:34");
$datetime2 = new DateTime("2018-05-17 17:04:34);
$interval = $datetime1->diff($datetime2);
echo $interval->format('H hours');
Strtotime has no problem parsing a time without a date.
No need to fake a date which will come back and bite you with daylight savings.
I also added a check to see if the start/end is "reversed".
$start= "2018-05-17 05:04:34";
$end = "2018-05-17 17:04:34";
//Note that it's intentionally reversed
$diff = strtotime(substr($start,11))-strtotime(substr($end,11));
//If the calculation was reversed add one day in seconds
if($diff <0) $diff += 86400;
If($diff >3600){
Echo "more than one hour";
}Else{
Echo "less than one hour";
}
https://3v4l.org/g1jZH
I believe only I have understood your question correctly.
I want to convert just hours (without date) e.g. 02:00:00 to timestamp.
There's no Date component here.
Okay, I assume they are of same date. If that's the case, just append an arbitrary date in front of the two to make the strtotime() function work:
$start = "05:04:34";
$end = "17:04:34";
$reported = strtotime("2018-05-17 " . $start);
$respons = strtotime("2018-05-17 " . $end);
$response_time = $respons - $reported;
if ($response_time > 3600)
echo "More than hour!";
else
echo "Less than hour!";
Note: This doesn't work if the start time is 17:00 and end time is say, 08:00 - which occurs in the next day. You have to make sure if the start time is greater than end time, then you have to add one more day to the end time.
I like the DateTime class, give this a try:
<?php
$reported = new DateTime('2018-05-17 05:04:34');
$reported->modify('+2 hours');
$now = new DateTime();
echo $now < $reported ? 'less than 2 hours' : 'more than 2 hours';
See it here https://3v4l.org/T7BEL
See the DateTime class docs here http://php.net/manual/en/class.datetime.php

Calculate the number of working day hours between two dates (e.g. 8:30 to 17:30 excluding weekends) [duplicate]

I have a function to return the difference between 2 dates, however I need to work out the difference in working hours, assuming Monday to Friday (9am to 5:30pm):
//DATE DIFF FUNCTION
// Set timezone
date_default_timezone_set("GMT");
// Time format is UNIX timestamp or
// PHP strtotime compatible strings
function dateDiff($time1, $time2, $precision = 6) {
// If not numeric then convert texts to unix timestamps
if (!is_int($time1)) {
$time1 = strtotime($time1);
}
if (!is_int($time2)) {
$time2 = strtotime($time2);
}
// If time1 is bigger than time2
// Then swap time1 and time2
if ($time1 > $time2) {
$ttime = $time1;
$time1 = $time2;
$time2 = $ttime;
}
// Set up intervals and diffs arrays
$intervals = array('year','month','day','hour','minute','second');
$diffs = array();
// Loop thru all intervals
foreach ($intervals as $interval) {
// Set default diff to 0
$diffs[$interval] = 0;
// Create temp time from time1 and interval
$ttime = strtotime("+1 " . $interval, $time1);
// Loop until temp time is smaller than time2
while ($time2 >= $ttime) {
$time1 = $ttime;
$diffs[$interval]++;
// Create new temp time from time1 and interval
$ttime = strtotime("+1 " . $interval, $time1);
}
}
$count = 0;
$times = array();
// Loop thru all diffs
foreach ($diffs as $interval => $value) {
// Break if we have needed precission
if ($count >= $precision) {
break;
}
// Add value and interval
// if value is bigger than 0
if ($value > 0) {
// Add s if value is not 1
if ($value != 1) {
$interval .= "s";
}
// Add value and interval to times array
$times[] = $value . " " . $interval;
$count++;
}
}
// Return string with times
return implode(", ", $times);
}
Date 1 = 2012-03-24 03:58:58
Date 2 = 2012-03-22 11:29:16
Is there a simple way of doing this, i.e - calculating the percentage of working hours in a week and dividing the difference using the above function - I have played around with this idea and got some very strange figures...
Or is there better way....?
This example uses PHP's built in DateTime classes to do the date math. How I approached this was to start by counting the number of full working days between the two dates and then multiply that by 8 (see notes). Then it gets the hours worked on the partial days and adds them to the total hours worked. Turning this into a function would be fairly straightforward to do.
Notes:
Does not take timestamps into account. But you already know how to do that.
Does not handle holidays. (That can be easily added by using an array of holidays and adding it to where you filter out Saturdays and Sundays).
Requires PHP 5.3.6+
Assumes an 8 hour workday. If employees do not take lunch change $hours = $days * 8; to $hours = $days * 8.5;
.
<?php
// Initial datetimes
$date1 = new DateTime('2012-03-22 11:29:16');
$date2 = new DateTime('2012-03-24 03:58:58');
// Set first datetime to midnight of next day
$start = clone $date1;
$start->modify('+1 day');
$start->modify('midnight');
// Set second datetime to midnight of that day
$end = clone $date2;
$end->modify('midnight');
// Count the number of full days between both dates
$days = 0;
// Loop through each day between two dates
$interval = new DateInterval('P1D');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
// If it is a weekend don't count it
if (!in_array($dt->format('l'), array('Saturday', 'Sunday'))) {
$days++;
}
}
// Assume 8 hour workdays
$hours = $days * 8;
// Get the number of hours worked on the first day
$date1->modify('5:30 PM');
$diff = $date1->diff($start);
$hours += $diff->h;
// Get the number of hours worked the second day
$date1->modify('8 AM');
$diff = $date2->diff($end);
$hours += $diff->h;
echo $hours;
See it in action
Reference
DateTime Class
DatePeriod Class
DateInterval Class
Here's what I've come up with.
My solution checks the start and end times of the original dates, and adjusts them according to the actual start and end times of the work day (if the original start time is before work's opening time, it sets it to the latter).
After this is done to both start and end times, the times are compared to retrieve a DateInterval diff, calculating the total days, hours, etc. The date range is then checked for any weekend days, and if found, one total day is reduced from the diff.
Finally, the hours are calculated as commented. :)
Cheers to John for inspiring some of this solution, particularly the DatePeriod to check for weekends.
Gold star to anyone who breaks this; I'll be happy to update if anyone finds a loophole!
Gold star to myself, I broke it! Yeah, weekends are still buggy (try starting at 4pm on Saturday and ending at 1pm Monday). I will conquer you, work hours problem!
Ninja edit #2: I think I took care of the weekend bugs by reverting the start and end times to the most recent respective weekday if they fall on a weekend. Got good results after testing a handful of date ranges (starting and ending on the same weekend barfs, as expected). I'm not entirely convinced this is as optimized / simple as it could be, but at least it works better now.
// Settings
$workStartHour = 9;
$workStartMin = 0;
$workEndHour = 17;
$workEndMin = 30;
$workdayHours = 8.5;
$weekends = ['Saturday', 'Sunday'];
$hours = 0;
// Original start and end times, and their clones that we'll modify.
$originalStart = new DateTime('2012-03-22 11:29:16');
$start = clone $originalStart;
// Starting on a weekend? Skip to a weekday.
while (in_array($start->format('l'), $weekends))
{
$start->modify('midnight tomorrow');
}
$originalEnd = new DateTime('2012-03-24 03:58:58');
$end = clone $originalEnd;
// Ending on a weekend? Go back to a weekday.
while (in_array($end->format('l'), $weekends))
{
$end->modify('-1 day')->setTime(23, 59);
}
// Is the start date after the end date? Might happen if start and end
// are on the same weekend (whoops).
if ($start > $end) throw new Exception('Start date is AFTER end date!');
// Are the times outside of normal work hours? If so, adjust.
$startAdj = clone $start;
if ($start < $startAdj->setTime($workStartHour, $workStartMin))
{
// Start is earlier; adjust to real start time.
$start = $startAdj;
}
else if ($start > $startAdj->setTime($workEndHour, $workEndMin))
{
// Start is after close of that day, move to tomorrow.
$start = $startAdj->setTime($workStartHour, $workStartMin)->modify('+1 day');
}
$endAdj = clone $end;
if ($end > $endAdj->setTime($workEndHour, $workEndMin))
{
// End is after; adjust to real end time.
$end = $endAdj;
}
else if ($end < $endAdj->setTime($workStartHour, $workStartMin))
{
// End is before start of that day, move to day before.
$end = $endAdj->setTime($workEndHour, $workEndMin)->modify('-1 day');
}
// Calculate the difference between our modified days.
$diff = $start->diff($end);
// Go through each day using the original values, so we can check for weekends.
$period = new DatePeriod($start, new DateInterval('P1D'), $end);
foreach ($period as $day)
{
// If it's a weekend day, take it out of our total days in the diff.
if (in_array($day->format('l'), ['Saturday', 'Sunday'])) $diff->d--;
}
// Calculate! Days * Hours in a day + hours + minutes converted to hours.
$hours = ($diff->d * $workdayHours) + $diff->h + round($diff->i / 60, 2);
As the old saying goes "if you want something done right do it yourself". Not saying this is optimal but its atleast returning the correct amount of hours for me.
function biss_hours($start, $end){
$startDate = new DateTime($start);
$endDate = new DateTime($end);
$periodInterval = new DateInterval( "PT1H" );
$period = new DatePeriod( $startDate, $periodInterval, $endDate );
$count = 0;
foreach($period as $date){
$startofday = clone $date;
$startofday->setTime(8,30);
$endofday = clone $date;
$endofday->setTime(17,30);
if($date > $startofday && $date <= $endofday && !in_array($date->format('l'), array('Sunday','Saturday'))){
$count++;
}
}
//Get seconds of Start time
$start_d = date("Y-m-d H:00:00", strtotime($start));
$start_d_seconds = strtotime($start_d);
$start_t_seconds = strtotime($start);
$start_seconds = $start_t_seconds - $start_d_seconds;
//Get seconds of End time
$end_d = date("Y-m-d H:00:00", strtotime($end));
$end_d_seconds = strtotime($end_d);
$end_t_seconds = strtotime($end);
$end_seconds = $end_t_seconds - $end_d_seconds;
$diff = $end_seconds-$start_seconds;
if($diff!=0):
$count--;
endif;
$total_min_sec = date('i:s',$diff);
return $count .":".$total_min_sec;
}
$start = '2014-06-23 12:30:00';
$end = '2014-06-27 15:45:00';
$go = biss_hours($start,$end);
echo $go;

php days between two dates list

Do you know what the problem is by looking at the code?
I would be happy if you helped me:
list($from_day,$from_month,$from_year) = explode(".","27.09.2012");
list($until_day,$until_month,$until_year) = explode(".","31.10.2012");
$iDateFrom = mktime(0,0,0,$from_month,$from_day,$from_year);
$iDateTo = mktime(0,0,0,$until_month,$until_day,$until_year);
while ($iDateFrom <= $iDateTo) {
print date('d.m.Y',$iDateFrom)."<br><br>";
$iDateFrom += 86400;
}
Date of writing the same problem 2 times
October (31) for writing 2 times in history draws the ends October 30th: (
27.09.2012
28.09.2012
...
26.10.2012
27.10.2012
[[28.10.2012]]
[[28.10.2012]]
29.10.2012
30.10.2012
Your problem is because you have set time to 00:00:00, set it to 12:00:00. That is because the Daylight saving time.
Stop using date() function, use Date and Time classes.
Solution (PHP >= 5.4):
$p = new DatePeriod(
new DateTime('2012-09-27'),
new DateInterval('P1D'),
(new DateTime('2012-10-31'))->modify('+1 day')
);
foreach ($p as $d) {
echo $d->format('d.m.Y') . "\n";
}
Solution (PHP < 5.4)
$end = new DateTime('2012-10-31');
$end->modify('+1 day');
$p = new DatePeriod(
new DateTime('2012-09-27'),
new DateInterval('P1D'),
$end
);
foreach ($p as $d) {
echo $d->format('d.m.Y') . "\n";
}
You have daylight savings time issues. Adding seconds from one timestamp to another is prone to problems around these sorts of edge conditions (leap days can be problematic is well), You should get in the habit of using PHP's DateTime and DateInterval objects. It makes working with dates a snap.
$start_date = new DateTime('2012-09-27');
$end_date = new DateTime('2012-10-31');
$current_date = clone $start_date;
$date_interval = new DateInterval('P1D');
while ($current_date < $end_date) {
// your logic here
$current_date->add($date_interval);
}
My idea for solving this would be something like this;
$firstDate = "27.09.2012";
$secondDate = "31.10.2012";
$daysDifference = (strtotime($secondDate) - strtotime($firstDate)) / (60 * 60 * 24);
$daysDifference = round($daysDifference);
for ($i = 0; $i <= $daysDifference; $i++)
{
echo date("d.m.Y", strtotime('+'.$i.' day', strtotime($firstDate))) . "<BR>";
}
This should solve your problem and be much easier to read (imho). I've just tested the code, and it outputs all dates and no doubles. It also saves you from all the daylight savings inconsistencies.
I don't know where you're from, but it's likely you're hitting daylight saving changeover in your timezone (it's Nov 4th where I live - exactly one week after Oct 28th). You can not rely on a day being exactly 86400 seconds long.
If you loop incrementing with mktime, you should be fine:
list($from_day,$from_month,$from_year) = explode(".","27.09.2012");
list($until_day,$until_month,$until_year) = explode(".","31.10.2012");
$iDateFrom = mktime(0,0,0,$from_month,$from_day,$from_year);
$iDateTo = mktime(0,0,0,$until_month,$until_day,$until_year);
while ($iDateFrom <= $iDateTo)
{
print date('d.m.Y',$iDateFrom)."<br><br>";
$from_day = $from_day + 1;
$iDateFrom = mktime(0,0,0,$from_month,$from_day,$from_year);
}
Even though $from_day will likely be going well over 31, mktime will make the math conversion for you. (ie 32 days in a 31 day month = day 1 of the next month)
EDIT: sorry, I had the incrementation in the wrong place.

Fill Out The Gaps Between Two Times With PHP

I've got to write a loop that should start and end between two times. I know there are many ways to skin this cat, but I'd like to see a real programmers approach to this function.
Essentially I have Wednesday, for instance, that opens at 6:00pm and closes at 10:30pm.
I'm looking to write a loop that will give me a table with all of the times in between those two in 15 minute intervals.
So, I basically want to build a one column table where each row is
6:00pm
6:15pm
7:15pm
etc...
My two variables to feed this function will be the open time and the close time.
Now don't accuse me of "write my code for me" posting. I'll happily give you my hacked solution on request, I'd just like to see how someone with real experience would create this function.
Thanks :)
$start = new DateTime("2011-08-18 18:00:00");
$end = new DateTime("2011-08-18 22:30:00");
$current = clone $start;
while ($current <= $end) {
echo $current->format("g:ia"), "\n";
$current->modify("+15 minutes");
}
Try it on Codepad: http://codepad.org/JwBDOQQE
PHP 5.3 introduced a class precisely for this purpose, DatePeriod.
$start = new DateTime("6:00pm");
$end = new DateTime("10:30pm");
$interval = new DateInterval('PT15M');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $time) {
echo $time->format('g:ia'), PHP_EOL;
}
echo $end->format('g:ia'); // end time is not part of the period
$start = strtotime('2011-08-11 18:00:00');
for ($i = 0; $i < 20; $i++) {
echo date('g:ia', $start + ($i * (15 * 60))), '<br>';
}
I would go with the DateTime functions and increase the time by 15 minutes every loop-turn as long as the current time is lower then the end-time.
EDIT: as user576875 has posted
$start_date = '2019-07-30 08:00:00';
$end_date = '2019-09-31 08:00:00';
while (strtotime($start_date) <= strtotime($end_date)) {
echo "$start_date<br>";
$start_date = date ("Y-m-d H:i:s", strtotime("+1 hours", strtotime($start_date)));
}

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