【问题标题】:Get number of weekdays in a given month获取给定月份的工作日数
【发布时间】:2012-01-13 20:29:54
【问题描述】:

我想计算给定月份和年份的工作日天数。工作日是指周一至周五。我该怎么做?

【问题讨论】:

    标签: php calendar days weekday weekend


    【解决方案1】:

    我创建了一个简单的函数,它采用 $first_day_of_month(星期天/星期一等工作日)。您可以像这样找出每月的第一天:

    date('N', strtotime(date("01-m-Y")));
    

    并使用可以像这样采购的 $month_last_date:

    date("t");
    

    函数如下:

    function workingDaysInMonth(int $first_day_of_month, int $month_last_date) : array
    {
        $working_days = [];
        $day = $first_day_of_month;
        $working_day_count = 0;
        for ($i = 1; $i <= $month_last_date; $i++) {
            if ($day == 8) {
                $day = 1;
            }
            if (!($day == 6 || $day == 7)) {
                $working_day_count++;
                $working_days[$i] = $working_day_count;
            }
            $day++;
        }
        return $working_days;
    }
    

    【讨论】:

      【解决方案2】:
      function workingDays($m,$y) {
          $days = cal_days_in_month(CAL_GREGORIAN, $m, $y);
          $workig_days = 0;
          $days_rest = array(5,6); //friday,saturday
          for ( $d=1 ; $d < $days+1 ; $d++ ) {
              if ( !in_array(date("w",strtotime("{$d}-{$m}-{$y}")),$days_rest)  ) {
                  $workig_days++;
              }
          }
          return $workig_days;
      }
      

      【讨论】:

        【解决方案3】:

        试试这个

        function getWeekdays($m, $y = NULL){
            $arrDtext = array('Mon', 'Tue', 'Wed', 'Thu', 'Fri');
        
            if(is_null($y) || (!is_null($y) && $y == ''))
                $y = date('Y');
        
            $d = 1;
            $timestamp = mktime(0,0,0,$m,$d,$y);
            $lastDate = date('t', $timestamp);
            $workingDays = 0;
            for($i=$d; $i<=$lastDate; $i++){
                if(in_array(date('D', mktime(0,0,0,$m,$i,$y)), $arrDtext)){
                    $workingDays++;
                }
            }
            return $workingDays;
        }
        

        【讨论】:

          【解决方案4】:

          这些函数没有循环。

          函数使用以下方法计算工作日数:

          • 每月第一个星期一的天数
          • 一个月的天数
          // main functions 
          // weekdays in month of year
          function calculateNumberOfWeekDaysAtDate($month, $year)
          {
              // I'm sorry, I don't know the right format for the $month and $year, I hope this is right.
              // PLEASE CORRECT IF WRONG
              $firstMondayInCurrentMonth = (int) date("j", strtotime("first monday of 01-$month-$year")); //get first monday in month for calculations
              $numberOfDaysOfCurrentMonth = (int) date("t", strtotime("01-$month-$year")); // number of days in month
          
              return calculateNumberOfWeekDaysFromFirstMondayAndNumberOfMonthDays($firstMondayInCurrentMonth, $numberOfDaysOfCurrentMonth);
          }
          
          // week days in current month
          function calculateNumberOfWeekDaysInCurrentMonth()
          {
              $firstMondayInCurrentMonth = (int) date("j", strtotime("first monday of this month")); //get first monday in month for calculations
              $numberOfDaysOfCurrentMonth = (int) date("t"); // number of days in this month
          
              return calculateNumberOfWeekDaysFromFirstMondayAndNumberOfMonthDays($firstMondayInCurrentMonth, $numberOfDaysOfCurrentMonth);
          }
          
          // helper functions
          function calculateNumberOfWeekDaysFromFirstMondayAndNumberOfMonthDays($firstMondayInCurrentMonth, $numberOfDaysOfCurrentMonth)
          {
              return $numberOfWeekDays = (($start = ($firstMondayInCurrentMonth - 3)) < 0 ? 0 : $start) + floor(($numberOfDaysOfCurrentMonth - ($firstMondayInCurrentMonth - 1)) / 7) * 5 + (($rest = (($numberOfDaysOfCurrentMonth - ($firstMondayInCurrentMonth - 1)) % 7)) <= 5 ? $rest : 5);
          }
          

          【讨论】:

            【解决方案5】:

            我想出了一个非循环函数。在性能方面要好得多。它可能看起来很乱,但它只需要询问 PHP 第一天的工作日和月份的天数:其余的都是基于逻辑的算术运算。

            function countWorkDays($year, $month)
            {
                $workingWeekdays   = 5;
                $firstDayTimestamp = mktime(0, 0, 0, $month, 1, $year);
                $firstDayWeekDay   = (int)date("N", $firstDayTimestamp); //1: monday, 7: saturday
                $upToDay           = (int)date("t", $firstDayTimestamp);
            
                $firstMonday = 1 === $firstDayWeekDay ? 1 : 9 - $firstDayWeekDay;
                $wholeWeeks  = $firstMonday < $upToDay ? (int)floor(($upToDay - $firstMonday + 1) / 7) : 0;
                $extraDays   = ($upToDay - $firstMonday + 1) % 7;
            
                $initialWorkdays      = $firstMonday > 1 && $firstDayWeekDay <= $workingWeekdays ? $workingWeekdays - $firstDayWeekDay + 1 : 0;
                $workdaysInWholeWeeks = $wholeWeeks * $workingWeekdays;
                $extraWorkdays        = $extraDays <= $workingWeekdays ? $extraDays : $workingWeekdays;
            
                return $initialWorkdays + $workdaysInWholeWeeks + $extraWorkdays;
            }
            

            【讨论】:

              【解决方案6】:

              从任意日期开始计算一个月的工作日:

              public function getworkd($mday)
              {
                  $dn = new DateTime($mday);
                  $dfrom = $dn->format('Y-m-01');
                  $dtill = $dn->format('Y-m-t');
                  $df = new DateTime($dfrom);
                  $dt = new DateTime($dtill);
                  $wdays = 0;
                  while($df<=$dt)
                  {
                      $dof= $df->format('D') ;
                      if( $dof == 'Sun' || $dof == 'Sat' ) ; else $wdays++;
                      $df->add(new DateInterval('P1D'));
                  }
                  return $wdays;
              }
              

              【讨论】:

                【解决方案7】:

                DateObject 方法:

                function getWorkingDays(DateTime $date) {
                    $month = clone $date;
                    $month->modify('last day of this month');
                    $workingDays = 0;
                    for ($i = $month->format('t'); $i > 28; --$i) {
                        if ($month->format('N') < 6) {
                            ++$workingDays;
                        }
                        $month->modify('-1 day');
                    }
                
                    return 20 + $workingDays;
                }
                

                【讨论】:

                  【解决方案8】:

                  获取两个日期之间无节假日的工作日:

                  使用示例:

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

                  输出:

                  3
                  

                  Link to the function

                  【讨论】:

                    【解决方案9】:

                    这会起作用

                    // oct. 2013
                    $month = 10;
                    
                    // loop through month days
                    for ($i = 1; $i <= 31; $i++) {
                    
                        // given month timestamp
                        $timestamp = mktime(0, 0, 0, $month, $i, 2012);
                    
                        // to be sure we have not gone to the next month
                        if (date("n", $timestamp) == $month) {
                    
                            // current day in the loop
                            $day = date("N", $timestamp);
                    
                            // if this is between 1 to 5, weekdays, 1 = Monday, 5 = Friday
                            if ($day == 1 OR $day <= 5) {
                    
                                // write it down now
                                $days[$day][] = date("j", $timestamp);
                            }
                        }
                    }
                    
                    // to see if it works :)
                    print_r($days);
                    

                    【讨论】:

                      【解决方案10】:

                      您无需计算当月的每一天。您已经知道前 28 天无论如何都包含 20 个工作日。您所要做的就是确定最后几天。将起始值更改为 29。然后将 20 个工作日添加到您的返回值。

                      function get_weekdays($m,$y) {
                      $lastday = date("t",mktime(0,0,0,$m,1,$y));
                      $weekdays=0;
                      for($d=29;$d<=$lastday;$d++) {
                          $wd = date("w",mktime(0,0,0,$m,$d,$y));
                          if($wd > 0 && $wd < 6) $weekdays++;
                          }
                      return $weekdays+20;
                      }
                      

                      【讨论】:

                      • 我喜欢这个解决方案,因为它对只做需要做的事情进行了逻辑分析。高效编程的真正本质。
                      【解决方案11】:

                      这是我能想到的最简单的代码。 您确实需要创建一个数组或数据库表来保存假期以获得真正的“工作日”计数,但这不是我们所要求的,所以就这样吧,希望这对某人有所帮助。

                      function get_weekdays($m,$y) {
                      $lastday = date("t",mktime(0,0,0,$m,1,$y));
                      $weekdays=0;
                      for($d=1;$d<=$lastday;$d++) {
                          $wd = date("w",mktime(0,0,0,$m,$d,$y));
                          if($wd > 0 && $wd < 6) $weekdays++;
                          }
                      return $weekdays;
                      }
                      

                      【讨论】:

                        【解决方案12】:

                        查找给定月份的最后一天和工作日
                        然后做一个简单的while循环,比如:-

                        $dates = explode(',', date('t,N', strtotime('2013-11-01')));
                        $day = $dates[1]; 
                        $tot = $dates[0]; 
                        $cnt = 0;
                        while ($tot>1)
                        {   
                            if ($day < 6)
                            {   
                                $cnt++;
                            }   
                            if ($day == 1)
                            {   
                                $day = 7;
                            }   
                            else
                            {   
                                $day--;
                            }   
                            $tot--;
                        }
                        

                        $cnt = 给定月份的工作日总数(周一至周五)

                        【讨论】:

                        • 此代码无法正常工作。它返回20 天为Dec 2013,但它应该是22。
                        【解决方案13】:

                        一些基本代码:

                        $month = 12;
                        $weekdays = array();
                        $d = 1;
                        
                        do {
                            $mk = mktime(0, 0, 0, $month, $d, date("Y"));
                            @$weekdays[date("w", $mk)]++;
                            $d++;
                        } while (date("m", $mk) == $month);
                        
                        print_r($weekdays);
                        

                        如果您的 PHP 错误警告未显示通知,请删除 @。

                        【讨论】:

                        • -1 因为我只是讨厌@ 的错误抑制,而且这段代码不能正常工作,它总是在下个月返回一个额外的日期。
                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2022-07-29
                        • 2013-12-05
                        • 2017-06-08
                        • 2014-07-09
                        • 1970-01-01
                        • 2012-10-19
                        相关资源
                        最近更新 更多