Create a function to add hours onto a deadline

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
recci
Forum Commoner
Posts: 42
Joined: Tue Jul 29, 2008 10:01 pm

Create a function to add hours onto a deadline

Post by recci »

Basically I am trying to create a basic case logging system and when somebody opens a new case, the case is assigned a priority with a given number of hours. For example priority 1 is 4 hours, 2 is 9 hours, 3 is 36hours and 4 is 63 hours.

Now adding hours onto a time stamp is easy but the catch is I need to take into account working hours which are 08:30 to 17:30 Monday to Friday. So if a case is given a 4 hour priority and the deadline for this falls after 17:30 on a week day then the deadline is extended to the next working day. Basically the deadline is 4 working hours.

Example:

Case created on: 19/05/2014 16:55 - with Priority 1 (4 Hours) Deadline is now: 20/05/2014 11:55

Make sense?

Another catch is I need to take into account hours On Hold and these two have to be only within working hours. But ill worry about that later.

I am trying to use the modern DateTime class for this as far as possible.

Here is what I have so far, I am struggling with the logic. It works if the deadline is within a day but if I add something like 63 hours is completely fails.

Where am I going wrong here? Brain is fried with this :(

Code: Select all

$deadline_c = $this->add_deadline(64);

function add_deadline($hours){
    $UTC = new DateTimeZone("UTC");
    $now = new DateTime(); //current date/time
    $today = new DateTime($now->format('Y-m-d'));//get today's date only
    $deadline = $now->add(new DateInterval("PT{$hours}H"));//add on hours from database

    //set working hours
    $workingday = new DateTime();
    $working_daystart = $workingday->setTime(8, 30);
    $working_dayend = $workingday->setTime(17, 30);

    //check if deadline is after 17:30
    if($deadline > $working_dayend){
        $interval = $deadline->diff($working_dayend);
        //time over the working day in hours and minutes
        $over = $interval->format("%H:%I");
        //split time
        $over = explode(':', $over);
        //set to next working since deadline is after 17;30
        $nextday = $today->modify('+ 1 day');
        $nextday->setTime(8, 30);
        //Set deadline to the next day and add on hours and mins
        $deadline = $nextday->add(new DateInterval("PT".$over[0]."H"));
        $deadline = $deadline->add(new DateInterval("PT".$over[1]."M"));
    }
    //get days to add on if the next day is a weekend day
    $ifweekend = $this->check_day($deadline);
    $deadline = $deadline->modify($ifweekend);

    $deadline->setTimezone($UTC);//adjust to UTC
    $new_time = $deadline->format('Y-m-d H:i');

    return $new_time;

}

//checks if passed in date falls on a weekend day and if so passes back day difference
function check_day($deadline) {

    $day = $deadline->format(l);

    if($day == 'Saturday'){

        return '+ 2 days';
    }
    elseif($deadline == 'Sunday'){
        return "+ 1 days";
    }
    else {
        return '+ 0 days';
    }
}

recci
Forum Commoner
Posts: 42
Joined: Tue Jul 29, 2008 10:01 pm

Re: Create a function to add hours onto a deadline

Post by recci »

Ok I have updated my function to this but it is still not working correclty:

this is returning back 2014-06-29 17:41:00 which is a sunday but sunday is not a working day.

$future = addRollover('2014-06-26 11:41:00', '+63 hours');
echo $future->format('Y-m-d H:i:s');

Code: Select all

<?php
function addRollover($givenDate, $addtime) {
$datetime = new DateTime($givenDate);
$datetime->modify($addtime);

if (in_array($datetime->format('l'), array('Sunday','Saturday')) || 
    17 < $datetime->format('G') || 
    (17 === $datetime->format('G') && 30 < $datetime->format('G'))
) {
    $endofday = clone $datetime;
    $endofday->setTime(17,30);
    $interval = $endofday->diff($datetime);

    $datetime->add(new DateInterval('P1D'));
    if (in_array($datetime->format('l'), array('Saturday', 'Sunday'))) {
        $datetime->modify('next Monday');
    }
    $datetime->setTime(8,30);
    $datetime->add($interval);
}

  return $datetime;
}
//this is returning back 2014-06-29 17:41:00 which is a sunday.
$future = addRollover('2014-06-26 11:41:00', '+63 hours');
echo $future->format('Y-m-d H:i:s');
See it in action: http://3v4l.org/Ac8ro

Here's an explanation of what's supposed to be going on in the function:

First we create a DateTime object representing our starting date/time

We then add the specified amount of time to it (see Supported Date and Time Formats)

We check to see if it is a weekend, after 6PM, or in the 5PM hour with more than 30 minutes passed (e.g. after 5:30PM)

If so we clone our datetime object and set it to 5:30PM

We then get the difference between the end time (5:30PM) and the modified time as a DateInterval object

We then progress to the next day

If the next day is a Saturday we progress to the next day

If the next day is a Sunday we progress to the next day

We then set our time to 8:30AM

We then add our difference between the end time (5:30PM) and the modified time to our datetime object

We return the object from the function
Last edited by recci on Thu Jun 26, 2014 7:09 am, edited 1 time in total.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Create a function to add hours onto a deadline

Post by Celauran »

Looks like your business days are from 08:30 through 17:30 and, save for priority 1, you're working in increments of 9 hours. Might be easier to change '+63 hours' to '+7 days' etc.
recci
Forum Commoner
Posts: 42
Joined: Tue Jul 29, 2008 10:01 pm

Re: Create a function to add hours onto a deadline

Post by recci »

The hours are stored in the database as an hours number so cant really do that. I also dont quite understand what your getting at.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Create a function to add hours onto a deadline

Post by Celauran »

recci wrote:I also dont quite understand what your getting at.
You don't see how 63 hours is seven 9-hour days?
recci
Forum Commoner
Posts: 42
Joined: Tue Jul 29, 2008 10:01 pm

Re: Create a function to add hours onto a deadline

Post by recci »

7x9 =63 bro but this isnt really helping. Just assume it has to be done in hours, using DateTime this should make no difference weather its hours or days anyway.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Create a function to add hours onto a deadline

Post by Celauran »

My point is that if you're adding 9 hours, checking if that extends past closing time and, if so, adding a day and adding the remaining hours after the next day's opening will give you the exact same result as just adding 1 day, but your way is significantly more complex. :shrug:
recci
Forum Commoner
Posts: 42
Joined: Tue Jul 29, 2008 10:01 pm

Re: Create a function to add hours onto a deadline

Post by recci »

I see your point but potentially any amout of hours could be used as the user has the ability to alter the priorities to anything they like.
recci
Forum Commoner
Posts: 42
Joined: Tue Jul 29, 2008 10:01 pm

Re: Create a function to add hours onto a deadline

Post by recci »

Ended up with this:

Code: Select all

function addRollover($givenDate, $addtime, $dayStart, $dayEnd, $weekDaysOnly) {
    //Break the working day start and end times into hours, minuets
    $dayStart = explode(',', $dayStart);
    $dayEnd = explode(',', $dayEnd);
    //Create required datetime objects and hours interval
    $datetime = new DateTime($givenDate);
    $endofday = clone $datetime;
    $endofday->setTime($dayEnd[0], $dayEnd[1]); //set end of working day time
    $interval = 'PT'.$addtime.'H';
    //Add hours onto initial given date
    $datetime->add(new DateInterval($interval));
    //if initial date + hours is after the end of working day
    if($datetime > $endofday)
    {
        //get the difference between the initial date + interval and the end of working day in seconds
        $seconds = $datetime->getTimestamp()- $endofday->getTimestamp();

        //Loop to next day
        while(true)
        {
            $endofday->add(new DateInterval('PT24H'));//Loop to next day by adding 24hrs
            $nextDay = $endofday->setTime($dayStart[0], $dayStart[1]);//Set day to working day start time
            //If the next day is on a weekend and the week day only param is true continue to add days
            if(in_array($nextDay->format('l'), array('Sunday','Saturday')) && $weekDaysOnly)
            {
                continue;
            }
            else //If not a weekend
            {
                $tmpDate = clone $nextDay;
                $tmpDate->setTime($dayEnd[0], $dayEnd[1]);//clone the next day and set time to working day end time
                $nextDay->add(new DateInterval('PT'.$seconds.'S')); //add the seconds onto the next day
                //if the next day time is later than the end of the working day continue loop
                if($nextDay > $tmpDate)
                {
                    $seconds = $nextDay->getTimestamp()-$tmpDate->getTimestamp();
                    $endofday = clone $tmpDate;
                    $endofday->setTime($dayStart[0], $dayStart[1]);
                }
                else //else return the new date.
                {
                    return $endofday;

                }
            }
        }
    }
    return $datetime;
}


$currentTime = '2014-06-27 08:30:00';
$dayStart = '8,30';
$dayEnd = '17,30';

$future = addRollover($currentTime, 65, $dayStart, $dayEnd, true);

echo "Results: </br>";
echo $future->format('Y-m-d H:i:s').'</br>';  

Post Reply