DateTime class create a function to add hours onto a deadline taking into account working hours and on hold time

前提是你 提交于 2019-12-11 16:14:23

问题


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 it returns back on a Sunday.

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

 <?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


回答1:


UPDATE 2

Updated the code as per based on suggestions provided

<?php
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>';


来源:https://stackoverflow.com/questions/24427553/datetime-class-create-a-function-to-add-hours-onto-a-deadline-taking-into-accoun

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!