【问题标题】:Next business day of given date in PHPPHP中给定日期的下一个工作日
【发布时间】:2011-07-28 18:26:58
【问题描述】:

有没有人有 PHP sn-p 来计算给定日期的下一个工作日? 例如,需要如何转换 YYYY-MM-DD 才能找出下一个工作日?

示例: 对于 03.04.2011 (DD-MM-YYYY),下一个工作日是 04.04.2011。 对于 08.04.2011,下一个工作日是 11.04.2011。

这是包含我需要知道下一个工作日的日期的变量

$cubeTime['time'];

变量包含:2011-04-01 sn-p 的结果应该是:2011-04-04

【问题讨论】:

标签: php date next


【解决方案1】:

这是在 PHP 中获取工作日(周一至周五)的最佳方式。

function days()
{
    $week=array();
    $weekday=["Monday","Tuesday","Wednesday","Thursday","Friday"];

    foreach ($weekday as $key => $value) 
    {
        $sort=$value." this week";
        $day=date('D', strtotime($sort)); 
        $date=date('d', strtotime($sort)); 
        $year=date('Y-m-d', strtotime($sort)); 

        $weeks['day']= $day;
        $weeks['date']= $date;
        $weeks['year']= $year;

        $week[]=$weeks;
    } 
    
    return $week;
}

希望这对你们有帮助。 谢谢,。

【讨论】:

    【解决方案2】:

    我在 PHP 中使用了以下方法,strtotime()闰年 2 月 月份不起作用。

    public static function nextWorkingDay($date, $addDays = 1)
    {
        if (strlen(trim($date)) <= 10) {
            $date = trim($date)." 09:00:00";
        }
    
        $date = new DateTime($date);
        //Add days
        $date->add(new DateInterval('P'.$addDays.'D'));
    
        while ($date->format('N') >= 5)
        {
            $date->add(new DateInterval('P1D'));
        }
    
        return $date->format('Y-m-d H:i:s');
    }
    

    此解决方案为 5 个工作日(如果您需要 6 或 4 天的工作,您可以更改)。如果你想排除更多的日子,比如假期,那么只需检查 while 循环中的另一个条件。

    //
    while ($date->format('N') >= 5 && !in_array($date->format('Y-m-d'), self::holidayArray()))
    

    【讨论】:

    • 你确定吗?非工作日不定义为周六和周日的国家呢?银行假期呢?
    • 一般工作日从星期一或星期日开始,用户可以从 PHP 中设置。除了那个银行假期和你必须从 $holidayArray 中提到的所有内容。根据您的评论,如果某些地方需要 4 个工作日,那么用户可以在 while 循环中更改 4 而不是 5 或 6。
    【解决方案3】:

    下个工作日

    从特定日期(不包括星期六或星期日)开始查找下一个工作日:

    echo date('Y-m-d', strtotime('2011-04-05 +1 Weekday'));
    

    当然,您也可以使用日期变量:

    $myDate = '2011-04-05';
    echo date('Y-m-d', strtotime($myDate . ' +1 Weekday'));
    

    更新:或者,如果您有权访问PHP's DateTime class(很可能):

    $date = new DateTime('2018-01-27');
    $date->modify('+7 weekday');
    echo $date->format('Y-m-d');
    

    想跳过假期?:

    虽然原始海报提到“我不需要考虑假期”,但如果您确实想忽略假期,请记住 - “假期”只是您不想包含的任何日期的数组,并且因国家、地区、公司、个人...等而异。

    只需将上述代码放入一个函数中即可排除/循环过去您不希望包含的日期。像这样的:

    $tmpDate = '2015-06-22';
    $holidays = ['2015-07-04', '2015-10-31', '2015-12-25'];
    $i = 1;
    $nextBusinessDay = date('Y-m-d', strtotime($tmpDate . ' +' . $i . ' Weekday'));
    
    while (in_array($nextBusinessDay, $holidays)) {
        $i++;
        $nextBusinessDay = date('Y-m-d', strtotime($tmpDate . ' +' . $i . ' Weekday'));
    }
    

    如果您愿意,我相信上面的代码可以简化或缩短。我试着用通俗易懂的方式来写。

    【讨论】:

    • @John Hunt - “假期”只是您不想包含的任何日期的数组,并且因国家、地区、公司、个人等而异。只需将其放入一个函数中,该函数排除/循环过去您不希望包含的日期......它很容易增加 - 只需使用 $i 而不是 1
    • @JohnHunt - 顺便说一句,OP 已经提到“我不需要考虑假期。”在我回答之前(请参阅他对 middaparkas 回答的评论)
    • 这是一个如何排除公共/银行/国家假日的工作示例:codepad.viper-7.com/NamlGN
    • 很抱歉,strtotime 在工作日存在一个已知错误,如果您执行 (+/-) 5 天的倍数,它会失败。 bugs.php.net/bug.php?id=63521。因此,作为一种解决方法,我使用 date('w', strtotime( $nextBusinessDay )) 添加了一个额外的验证,以查看日期返回是星期六还是星期日,然后将日期调整 1 天或 2 天。
    • 它帮助我进行了微小的修改。谢谢
    【解决方案4】:

    你可以做这样的事情。

    /**
     * @param string $date
     * @param DateTimeZone|null|null $DateTimeZone
     * @return \NavigableDate\NavigableDateInterface
     */
    function getNextBusinessDay(string $date, ? DateTimeZone $DateTimeZone = null):\NavigableDate\NavigableDateInterface
    {
        $Date = \NavigableDate\NavigableDateFacade::create($date, $DateTimeZone);
    
        $NextDay = $Date->nextDay();
        while(true)
        {
            $nextDayIndexInTheWeek = (int) $NextDay->format('N');
    
            // check if the day is between Monday and Friday. In DateTime class php, Monday is 1 and Friday is 5
            if ($nextDayIndexInTheWeek >= 1 && $nextDayIndexInTheWeek <= 5)
            {
                break;
            }
            $NextDay = $NextDay->nextDay();
        }
    
        return $NextDay;
    }
    
    $date = '2017-02-24';
    $NextBussinessDay = getNextBusinessDay($date);
    
    var_dump($NextBussinessDay->format('Y-m-d'));
    

    输出:

    string(10) "2017-02-27"
    

    \NavigableDate\NavigableDateFacade::create($date, $DateTimeZone),由https://packagist.org/packages/ishworkh/navigable-date 提供的php 库提供。您需要先使用 Composer 或直接下载将此库包含在您的项目中。

    【讨论】:

      【解决方案5】:

      请看下面的例子:

      $startDate = new DateTime( '2013-04-01' );    //intialize start date
      $endDate = new DateTime( '2013-04-30' );    //initialize end date
      $holiday = array('2013-04-11','2013-04-25');  //this is assumed list of holiday
      $interval = new DateInterval('P1D');    // set the interval as 1 day
      $daterange = new DatePeriod($startDate, $interval ,$endDate);
      foreach($daterange as $date){
      if($date->format("N") <6 AND !in_array($date->format("Y-m-d"),$holiday))
      $result[] = $date->format("Y-m-d");
      }
      echo "<pre>";print_r($result);
      

      欲了解更多信息:http://goo.gl/YOsfPX

      【讨论】:

        【解决方案6】:

        对于英国假期,您可以使用

        https://www.gov.uk/bank-holidays#england-and-wales

        ICS 格式数据易于解析。我的建议是……

        # $date must be in YYYY-MM-DD format
        # You can pass in either an array of holidays in YYYYMMDD format
        # OR a URL for a .ics file containing holidays
        # this defaults to the UK government holiday data for England and Wales
        function addBusinessDays($date,$numDays=1,$holidays='') {
            if ($holidays==='') $holidays = 'https://www.gov.uk/bank-holidays/england-and-wales.ics';
        
            if (!is_array($holidays)) {
                $ch = curl_init($holidays);
                curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
                $ics = curl_exec($ch);
                curl_close($ch);
                $ics = explode("\n",$ics);
                $ics = preg_grep('/^DTSTART;/',$ics);
                $holidays = preg_replace('/^DTSTART;VALUE=DATE:(\\d{4})(\\d{2})(\\d{2}).*/s','$1-$2-$3',$ics);
            }
        
            $addDay = 0;
            while ($numDays--) {
                while (true) {
                    $addDay++;
                    $newDate = date('Y-m-d', strtotime("$date +$addDay Days"));
                    $newDayOfWeek = date('w', strtotime($newDate));
                    if ( $newDayOfWeek>0 && $newDayOfWeek<6 && !in_array($newDate,$holidays)) break;
                }
            }
        
            return $newDate;
        }
        

        【讨论】:

        • 正是我想要的。谢谢
        【解决方案7】:

        当我在一个丹麦网站上工作时,我偶然发现了这个线程,我需要编写一个“次日交付”PHP 脚本。

        这是我想出的(这将以丹麦语显示下一个工作日的名称,如果当前时间超过给定限制,则下一个工作日 + 1)

        $day["Mon"] = "Mandag"; 
        $day["Tue"] = "Tirsdag";
        $day["Wed"] = "Onsdag";
        $day["Thu"] = "Torsdag";
        $day["Fri"] = "Fredag";
        $day["Sat"] = "Lørdag";
        $day["Sun"] = "Søndag";
        
        date_default_timezone_set('Europe/Copenhagen');
        
        $date = date('l');
        $checkTime = '1400';
        $date2 = date(strtotime($date.' +1 Weekday'));
        if( date( 'Hi' ) >= $checkTime) {
        $date2 = date(strtotime($date.' +2 Weekday'));
        }
        if (date('l') == 'Saturday'){
        $date2 = date(strtotime($date.' +2 Weekday'));
        }
        if (date('l') == 'Sunday') {
        $date2 = date(strtotime($date.' +2 Weekday'));
        }
        echo '<p>Næste levering: <span>'.$day[date("D", $date2)].'</span></p>';
        

        正如您在示例代码中看到的,$checkTime 是我设置时间限制的地方,它决定了第二天交货是 +1 个工作日还是 +2 个工作日。

        '1400' = 14:00 小时

        我知道 if 语句可以更压缩,但我将我的代码展示给人们以便人们轻松理解它的工作方式。

        我希望有人可以使用这个小sn-p。

        【讨论】:

          【解决方案8】:

          此函数将计算未来或过去的工作日。参数是天数、向前 (1) 或向后 (0) 以及日期。如果没有提供日期,将使用今天的日期:

          // returned $date Y/m/d
          function work_days_from_date($days, $forward, $date=NULL) 
          {
              if(!$date)
              {
                  $date = date('Y-m-d'); // if no date given, use todays date
              }
          
              while ($days != 0) 
              {
                  $forward == 1 ? $day = strtotime($date.' +1 day') : $day = strtotime($date.' -1 day');
                  $date = date('Y-m-d',$day);
                  if( date('N', strtotime($date)) <= 5) // if it's a weekday
                  {
                    $days--;
                  }
              }
              return $date;
          }
          

          【讨论】:

            【解决方案9】:
            function next_business_day($date) {
              $add_day = 0;
              do {
                $add_day++;
                $new_date = date('Y-m-d', strtotime("$date +$add_day Days"));
                $new_day_of_week = date('w', strtotime($new_date));
              } while($new_day_of_week == 6 || $new_day_of_week == 0);
            
              return $new_date;
            }
            

            此函数应忽略周末(6 = 星期六,0 = 星期日)。

            【讨论】:

              【解决方案10】:

              你需要做的是:

              1. 将提供的日期转换为时间戳。

              2. 将它与或wN 格式化程序一起用于PHP 的date 命令告诉您它是星期几。

              3. 如果不是“工作日”,您可以将时间戳增加一天(86400 秒)并再次检查,直到遇到工作日。

              注意:因为这是真正的工作,您还需要排除任何银行或公共假期等。

              【讨论】:

              • 我不需要考虑假期。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2013-08-23
              • 2013-10-06
              • 2014-04-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多