(PHP) Timestamp for a WORKING date/time a number of minutes/days from a given start date

3 12 2009

That title long enough? It’s hard to describe this function, but you get it now, right?

Based on this function here.

/**
* getTimePlusOffsetDuringWork
*
* The function returns the timestamp of a date + business minutes
* @param timestamp|string startDate Beginning date/time as base for offset
* @param numeric offsetMinutes Work minutes to add to the startDate
* @param mixed Array of holiday dates, preferrably in the 'MM-DD' format
* @return integer Timestamp for the resulting time during Work hours,
*     given the simple equation StartDate + offsetMinutes.
*     Ignores after-hours, weekends, and holidays [for the first year after the startDate].
* Limitations: too many to list entirely.
*     9am-5pm work day only
*     1 year of holidays only
*     no week/weekday dependent holidays
*     Need to set timezone prior to calling this function if used outside of the server's timezone
*     Relies on English locale setting
* @author Zvi Landsman
**/
function getTimePlusOffsetDuringWork($startDate,$offsetMinutes,$holidays=array("12-25","12-26","01-01","07-04")){
    $j = $i = 0; //changed this to 0 or you were always starting one day ahead
    $tmp1 = validation::is_timestamp($startDate)?$startDate:strtotime($startDate); //worked out a timstamp to start with
    $offsetMinutes = round($offsetMinutes);
    $simple_time = strtotime("+$offsetMinutes minutes", $tmp1);
    if($simple_time <= strtotime('17:00', $tmp1))
    {
        //offset is still today
        return $simple_time;
    }
    //Check if start time is after-hours 
    if ($tmp1 > strtotime('17:00', $tmp1))
    {
        $tmp1 = strtotime("09:00 +1 day", $tmp1);
    }
    //This checks if the minute offset puts us into tomorrow
    $newdate = $tmp1;
    $minutes_left = $offsetMinutes%480;
    $newtime = strtotime("+ $minutes_left minutes", $newdate);
    if($newtime > strtotime('17:00', $newdate))
    {
        $j++;
        $minutes_left = round(($newtime - strtotime('17:00', $newdate))/60);
        $tmp1 = strtotime("+ $minutes_left minutes", strtotime("09:00 +1 day", $tmp1));
    }
    else
    {
        $tmp1 = strtotime("+ $minutes_left minutes", $tmp1);
    }

    //create the holiday list for the first upcoming occurances only
    $holidayList = array();
    foreach ($holidays as $holiday)
    {
        $time_stamp=strtotime($holiday, $tmp1);

        $date=($time_stamp < $tmp1)?
            strftime("%d-%m-%Y",strtotime($holiday.' +1 year')):
            strftime("%d-%m-%Y",$time_stamp);
        $holidayList[] = $date;
    }

    $days_to_offset = floor($offsetMinutes/480);
    while($i < $days_to_offset)
    {
        $tmp2 = strtotime("+$j day", $tmp1);
        $day = strftime("%A",$tmp2);

        $tmp = strftime("%d-%m-%Y",$tmp2);
        if(($day != "Sunday") && ($day != "Saturday" )&&(!in_array($tmp, $holidayList)))
        {
            $i = $i + 1;
            $j = $j + 1;

        }
        else
        {
            $j = $j + 1;

        }
    }
    //$j = $j -1;
    return strtotime("+$j days",$tmp1);
}

I’m completely open to improvements in the comments.