Calculate business days

后端 未结 30 1822
猫巷女王i
猫巷女王i 2020-11-22 05:16

I need a method for adding \"business days\" in PHP. For example, Friday 12/5 + 3 business days = Wednesday 12/10.

At a minimum I need the code to understand weekend

相关标签:
30条回答
  • 2020-11-22 06:02

    Get the number of working days without holidays between two dates :

    Use example:

    echo number_of_working_days('2013-12-23', '2013-12-29');
    

    Output:

    3
    

    Function:

    function number_of_working_days($from, $to) {
        $workingDays = [1, 2, 3, 4, 5]; # date format = N (1 = Monday, ...)
        $holidayDays = ['*-12-25', '*-01-01', '2013-12-23']; # variable and fixed holidays
    
        $from = new DateTime($from);
        $to = new DateTime($to);
        $to->modify('+1 day');
        $interval = new DateInterval('P1D');
        $periods = new DatePeriod($from, $interval, $to);
    
        $days = 0;
        foreach ($periods as $period) {
            if (!in_array($period->format('N'), $workingDays)) continue;
            if (in_array($period->format('Y-m-d'), $holidayDays)) continue;
            if (in_array($period->format('*-m-d'), $holidayDays)) continue;
            $days++;
        }
        return $days;
    }
    
    0 讨论(0)
  • 2020-11-22 06:02

    Here is a function for adding buisness days to a date

     function add_business_days($startdate,$buisnessdays,$holidays,$dateformat){
      $i=1;
      $dayx = strtotime($startdate);
      while($i < $buisnessdays){
       $day = date('N',$dayx);
       $date = date('Y-m-d',$dayx);
       if($day < 6 && !in_array($date,$holidays))$i++;
       $dayx = strtotime($date.' +1 day');
      }
      return date($dateformat,$dayx);
     }
    
     //Example
     date_default_timezone_set('Europe\London');
     $startdate = '2012-01-08';
     $holidays=array("2012-01-10");
     echo '<p>Start date: '.date('r',strtotime( $startdate));
     echo '<p>'.add_business_days($startdate,7,$holidays,'r');
    

    Another post mentions getWorkingDays (from php.net comments and included here) but I think it breaks if you start on a Sunday and finish on a work day.

    Using the following (you'll need to include the getWorkingDays function from previous post)

     date_default_timezone_set('Europe\London');
     //Example:
     $holidays = array('2012-01-10');
     $startDate = '2012-01-08';
     $endDate = '2012-01-13';
     echo getWorkingDays( $startDate,$endDate,$holidays);
    

    Gives the result as 5 not 4

    Sun, 08 Jan 2012 00:00:00 +0000 weekend
    Mon, 09 Jan 2012 00:00:00 +0000
    Tue, 10 Jan 2012 00:00:00 +0000 holiday
    Wed, 11 Jan 2012 00:00:00 +0000
    Thu, 12 Jan 2012 00:00:00 +0000
    Fri, 13 Jan 2012 00:00:00 +0000 
    

    The following function was used to generate the above.

         function get_working_days($startDate,$endDate,$holidays){
          $debug = true;
          $work = 0;
          $nowork = 0;
          $dayx = strtotime($startDate);
          $endx = strtotime($endDate);
          if($debug){
           echo '<h1>get_working_days</h1>';
           echo 'startDate: '.date('r',strtotime( $startDate)).'<br>';
           echo 'endDate: '.date('r',strtotime( $endDate)).'<br>';
           var_dump($holidays);
           echo '<p>Go to work...';
          }
          while($dayx <= $endx){
           $day = date('N',$dayx);
           $date = date('Y-m-d',$dayx);
           if($debug)echo '<br />'.date('r',$dayx).' ';
           if($day > 5 || in_array($date,$holidays)){
            $nowork++;
         if($debug){
          if($day > 5)echo 'weekend';
          else echo 'holiday';
         }
           } else $work++;
           $dayx = strtotime($date.' +1 day');
          }
          if($debug){
          echo '<p>No work: '.$nowork.'<br>';
          echo 'Work: '.$work.'<br>';
          echo 'Work + no work: '.($nowork+$work).'<br>';
          echo 'All seconds / seconds in a day: '.floatval(strtotime($endDate)-strtotime($startDate))/floatval(24*60*60);
          }
          return $work;
         }
    
        date_default_timezone_set('Europe\London');
         //Example:
         $holidays=array("2012-01-10");
         $startDate = '2012-01-08';
         $endDate = '2012-01-13';
    //broken
         echo getWorkingDays( $startDate,$endDate,$holidays);
    //works
         echo get_working_days( $startDate,$endDate,$holidays);
    

    Bring on the holidays...

    0 讨论(0)
  • 2020-11-22 06:02

    This code snippet is very easy to calculate business day without week end and holidays:

    function getWorkingDays($startDate,$endDate,$offdays,$holidays){
    $endDate = strtotime($endDate);
    $startDate = strtotime($startDate);
    $days = ($endDate - $startDate) / 86400 + 1;
    $counter=0;
    for ($i = 1; $i <= $days; $i++) {
        $the_first_day_of_week = date("N", $startDate);
        $startDate+=86400;
    if (!in_array($the_first_day_of_week, $offdays) && !in_array(date("Y-m-
    d",$startDate), $holidays)) {
    $counter++;
    }
    
    }   
    return $counter;
    }
    //example to use
    $holidays=array("2017-07-03","2017-07-20");
    $offdays=array(5,6);//weekend days Monday=1 .... Sunday=7
    echo getWorkingDays("2017-01-01","2017-12-31",$offdays,$holidays)
    
    0 讨论(0)
  • 2020-11-22 06:03

    This is another solution, it is nearly 25% faster than checking holidays with in_array:

    /**
     * Function to calculate the working days between two days, considering holidays.
     * @param string $startDate -- Start date of the range (included), formatted as Y-m-d.
     * @param string $endDate -- End date of the range (included), formatted as Y-m-d.
     * @param array(string) $holidayDates -- OPTIONAL. Array of holidays dates, formatted as Y-m-d. (e.g. array("2016-08-15", "2016-12-25"))
     * @return int -- Number of working days.
     */
    function getWorkingDays($startDate, $endDate, $holidayDates=array()){
        $dateRange = new DatePeriod(new DateTime($startDate), new DateInterval('P1D'), (new DateTime($endDate))->modify("+1day"));
        foreach ($dateRange as $dr) { if($dr->format("N")<6){$workingDays[]=$dr->format("Y-m-d");} }
        return count(array_diff($workingDays, $holidayDates));
    }
    
    0 讨论(0)
  • 2020-11-22 06:04

    Here is another solution without for loop for each day.

    $from = new DateTime($first_date);
    $to = new DateTime($second_date);
    
    $to->modify('+1 day');
    $interval = $from->diff($to);
    $days = $interval->format('%a');
    
    $extra_days = fmod($days, 7);
    $workdays = ( ( $days - $extra_days ) / 7 ) * 5;
    
    $first_day = date('N', strtotime($first_date));
    $last_day = date('N', strtotime("1 day", strtotime($second_date)));
    $extra = 0;
    if($first_day > $last_day) {
       if($first_day == 7) {
           $first_day = 6;
       }
    
       $extra = (6 - $first_day) + ($last_day - 1);
       if($extra < 0) {
           $extra = $extra * -1;
       }
    }
    if($last_day > $first_day) {
        $extra = $last_day - $first_day;
    }
    $days = $workdays + $extra
    
    0 讨论(0)
  • 2020-11-22 06:06

    Below is the working code to calculate working business days from a given date.

    <?php
    $holiday_date_array = array("2016-01-26", "2016-03-07", "2016-03-24", "2016-03-25", "2016-04-15", "2016-08-15", "2016-09-12", "2016-10-11", "2016-10-31");
    $date_required = "2016-03-01";
    
    function increase_date($date_required, $holiday_date_array=array(), $days = 15){
        if(!empty($date_required)){
            $counter_1=0;
            $incremented_date = '';
            for($i=1; $i <= $days; $i++){
                $date = strtotime("+$i day", strtotime($date_required));
                $day_name = date("D", $date);
                $incremented_date = date("Y-m-d", $date);
                if($day_name=='Sat'||$day_name=='Sun'|| in_array($incremented_date ,$holiday_date_array)==true){
                    $counter_1+=1;
                }
            }
            if($counter_1 > 0){
                return increase_date($incremented_date, $holiday_date_array, $counter_1);
            }else{
                return $incremented_date;
            }
        }else{
            return 'invalid';
        }
    }
    
    echo increase_date($date_required, $holiday_date_array, 15);
    ?>
    
    //output after adding 15 business working days in 2016-03-01 will be "2016-03-23"
    
    0 讨论(0)
提交回复
热议问题