PHP Add two hours to a date within given hours usi

2019-03-04 01:18发布

问题:

How would I structure the conditions to add two hours only to dates between 08:30 in the morning until 18:30 of the evening, excluding Saturday and Sunday?

In the case that a time near the border (e.g. 17:30 on Tuesday) is given, the left over time should be added to the beginning of the next "valid" time period.

For example: if the given date was in 17:30 on Tuesday, the two hour addition would result in 9:30 on Wednesday (17:30 + 1 hour = 18:30, 8:30 + the remainder 1 hour = 9:30). Or if the given date was in 17:00 on Friday, the result would be 9:00 on Monday (17:00 Friday + 1.5 hours = 18:30, 8:30 Monday + the remainder .5 hours = 9:00)

I know how to simply add two hours, as follows:

$idate1 = strtotime($_POST['date']);
$time1 = date('Y-m-d G:i', strtotime('+120 minutes', $idate1));
$_POST['due_date']  = $time1;

i have tried this this function and it works great except when i use a date like ( 2013-11-26 12:30 ) he gives me ( 2013-11-27 04:30:00 ) the problem is with 12:30

function addRollover($givenDate, $addtime) {
    $starttime = 8.5*60; //Start time in minutes (decimal hours * 60)
    $endtime = 18.5*60; //End time in minutes (decimal hours * 60)

    $givenDate = strtotime($givenDate);

    //Get just the day portion of the given time
    $givenDay = strtotime('today', $givenDate);
    //Calculate what the end of today's period is
    $maxToday = strtotime("+$endtime minutes", $givenDay);
    //Calculate the start of the next period
    $nextPeriod = strtotime("tomorrow", $givenDay); //Set it to the next day
    $nextPeriod = strtotime("+$starttime minutes", $nextPeriod);  //And add the starting time
    //If it's the weekend, bump it to Monday
    if(date("D", $nextPeriod) == "Sat") {
        $nextPeriod = strtotime("+2 days", $nextPeriod);
    }

    //Add the time period to the new day
    $newDate = strtotime("+$addtime", $givenDate);
    //print "$givenDate -> $newDate\n";
    //print "$maxToday\n";
    //Get the new hour as a decimal (adding minutes/60)
    $hourfrac = date('H',$newDate) + date('i',$newDate)/60;
    //print "$hourfrac\n";

    //Check if we're outside the range needed
    if($hourfrac < $starttime || $hourfrac > $endtime) {
        //We're outside the range, find the remainder and add it on
        $remainder = $newDate - $maxToday;
        //print "$remainder\n";
        $newDate = $nextPeriod + $remainder;
    }

    return $newDate;
}

回答1:

I don't know if you still need this but here it is anyway. Requires PHP 5.3 or higher

<?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 = $datetime->diff($endofday);

        $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;
}

$future = addRollover('2014-01-03 15:15:00', '+4 hours');
echo $future->format('Y-m-d H:i:s');

See it in action

Here's an explanation of what's going on:

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

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

  3. 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)

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

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

  6. We then progress to the next day

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

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

  9. We then set our time to 8:30AM

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

  11. We return the object from the function