【问题标题】:php weeks between 2 datesphp 两个日期之间的周数
【发布时间】:2010-06-12 11:29:01
【问题描述】:

您好,如何查找两个日期之间的周数和每个星期一的日期。从 10-07-2009 到今天。

注意:还要考虑闰年和其他与日期相关的约束。

【问题讨论】:

  • 你的日期是什么格式的?
  • 其实格式无关紧要,反正都会转换成unix时间戳

标签: php date


【解决方案1】:

这是使用 DateTime 的替代解决方案:-

function datediffInWeeks($date1, $date2)
{
    if($date1 > $date2) return datediffInWeeks($date2, $date1);
    $first = DateTime::createFromFormat('m/d/Y', $date1);
    $second = DateTime::createFromFormat('m/d/Y', $date2);
    return floor($first->diff($second)->days/7);
}

var_dump(datediffInWeeks('1/2/2013', '6/4/2013'));// 21

See it working

【讨论】:

  • 我认为这个答案比接受的更完整,特别是如果@Piskvor 在说 datediff 有错误时是正确的。
  • the floor here --- floor($first->diff($second)->days/7) 给我带来了问题......所以这可能是您的程序是否需要的问题将 2.8 周视为 3 周或 2 周。
  • @Aukhan 然后随意修改它以适应 :) 此处发布的 sn-p 代码不可能适合所有场景,它们只是建议的起点。也许round() 更适合你?
  • @vascowhite ... 是的 :) 我那天确实修改了它以满足我的需要,我想通过 ceil() 来查看它。谢谢sn-p!我认为应该成为核心 php 的一部分……喜欢 moment.js 处理这些事情的方式;)
【解决方案2】:
echo datediff('ww', '9 July 2003', '4 March 2004', false);

在以下网站上找到该功能: http://www.addedbytes.com/code/php-datediff-function/

更新

链接现已损坏(2017 年 9 月),因此从 webarchive 中提取以下函数:

<?php

/**
 * @param $interval
 * @param $datefrom
 * @param $dateto
 * @param bool $using_timestamps
 * @return false|float|int|string
 */
function datediff($interval, $datefrom, $dateto, $using_timestamps = false)
{
    /*
    $interval can be:
    yyyy - Number of full years
    q    - Number of full quarters
    m    - Number of full months
    y    - Difference between day numbers
           (eg 1st Jan 2004 is "1", the first day. 2nd Feb 2003 is "33". The datediff is "-32".)
    d    - Number of full days
    w    - Number of full weekdays
    ww   - Number of full weeks
    h    - Number of full hours
    n    - Number of full minutes
    s    - Number of full seconds (default)
    */

    if (!$using_timestamps) {
        $datefrom = strtotime($datefrom, 0);
        $dateto   = strtotime($dateto, 0);
    }

    $difference        = $dateto - $datefrom; // Difference in seconds
    $months_difference = 0;

    switch ($interval) {
        case 'yyyy': // Number of full years
            $years_difference = floor($difference / 31536000);
            if (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom), date("j", $datefrom), date("Y", $datefrom)+$years_difference) > $dateto) {
                $years_difference--;
            }

            if (mktime(date("H", $dateto), date("i", $dateto), date("s", $dateto), date("n", $dateto), date("j", $dateto), date("Y", $dateto)-($years_difference+1)) > $datefrom) {
                $years_difference++;
            }

            $datediff = $years_difference;
        break;

        case "q": // Number of full quarters
            $quarters_difference = floor($difference / 8035200);

            while (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom)+($quarters_difference*3), date("j", $dateto), date("Y", $datefrom)) < $dateto) {
                $months_difference++;
            }

            $quarters_difference--;
            $datediff = $quarters_difference;
        break;

        case "m": // Number of full months
            $months_difference = floor($difference / 2678400);

            while (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom)+($months_difference), date("j", $dateto), date("Y", $datefrom)) < $dateto) {
                $months_difference++;
            }

            $months_difference--;

            $datediff = $months_difference;
        break;

        case 'y': // Difference between day numbers
            $datediff = date("z", $dateto) - date("z", $datefrom);
        break;

        case "d": // Number of full days
            $datediff = floor($difference / 86400);
        break;

        case "w": // Number of full weekdays
            $days_difference  = floor($difference / 86400);
            $weeks_difference = floor($days_difference / 7); // Complete weeks
            $first_day        = date("w", $datefrom);
            $days_remainder   = floor($days_difference % 7);
            $odd_days         = $first_day + $days_remainder; // Do we have a Saturday or Sunday in the remainder?

            if ($odd_days > 7) { // Sunday
                $days_remainder--;
            }

            if ($odd_days > 6) { // Saturday
                $days_remainder--;
            }

            $datediff = ($weeks_difference * 5) + $days_remainder;
        break;

        case "ww": // Number of full weeks
            $datediff = floor($difference / 604800);
        break;

        case "h": // Number of full hours
            $datediff = floor($difference / 3600);
        break;

        case "n": // Number of full minutes
            $datediff = floor($difference / 60);
        break;

        default: // Number of full seconds (default)
            $datediff = $difference;
        break;
    }

    return $datediff;
}

【讨论】:

  • 如果不是因为包括 2012 年(和 2016 年、2020 年和 2024 年)在内的许多范围内的不那么微妙的错误,那就太好了:2 月 29 日。
  • 最好把datediff的代码加进去,以防链接失效。
  • 我到底是如何在谷歌上搜索一个函数来查找两个日期之间的周差,并最终出现在 StackOverflow 上……阅读链接到我自己网站的评论和我已经编写的代码解决这个问题?我想我正在失去它......
  • @Piskvor 声称对于这样一个复杂的函数,你应该有某种可重现的代码,它工作得很好,我没有看到任何错误
  • @DaveChild 发现这个函数可以计算两个日期之间的周数,你见过吗?
【解决方案3】:
$diff = strtotime($dateto, 0) - strtotime($datefrom, 0);
echo floor($diff / 604800);

【讨论】:

  • 夏令时有问题。可能的解决方案:使用 UTC,使用 round 代替 floor,或使用 DateTime::diff 代替减法。
  • 什么是夏令时@Brilliand?
  • @Radmation 夏令时
【解决方案4】:

这项工作很棒

function weeks_between($datefrom, $dateto)
    {
        $datefrom = DateTime::createFromFormat('d/m/Y H:i:s',$datefrom);
        $dateto = DateTime::createFromFormat('d/m/Y H:i:s',$dateto);
        $interval = $datefrom->diff($dateto);
        $week_total = $interval->format('%a')/7;
        return floor($week_total);

    }

weeks_between("25/02/2000 11:30:00","05/06/2015 11:29:59")

【讨论】:

    【解决方案5】:

    以下函数计算两个时间戳之间的“口语周”(即,如果您在星期六,则星期一是下周)。

    function days_between($datefrom,$dateto){
        $fromday_start = mktime(0,0,0,date("m",$datefrom),date("d",$datefrom),date("Y",$datefrom));
        $diff = $dateto - $datefrom;
        $days = intval( $diff / 86400 ); // 86400  / day
    
        if( ($datefrom - $fromday_start) + ($diff % 86400) > 86400 )
            $days++;
    
        return  $days;
    }
    
    function weeks_between($datefrom, $dateto)
    {
        $day_of_week = date("w", $datefrom);
        $fromweek_start = $datefrom - ($day_of_week * 86400) - ($datefrom % 86400);
        $diff_days = days_between($datefrom, $dateto);
        $diff_weeks = intval($diff_days / 7);
        $seconds_left = ($diff_days % 7) * 86400;
    
        if( ($datefrom - $fromweek_start) + $seconds_left > 604800 )
            $diff_weeks ++;
    
        return $diff_weeks;
    }
    

    【讨论】:

      【解决方案6】:

      我从上面更新了 Tom 的代码,以使函数自动检测字符串或 int 日期/时间。

      <?php
      /**
       * @param $interval
       * @param $datefrom
       * @param $dateto
       * @param bool $using_timestamps // Removed 08-29-2019 Jay Simons - Now auto-detects
       * @return false|float|int|string
       */
      function datediff($interval, $datefrom, $dateto)
      {
          /*
          $interval can be:
          yyyy - Number of full years
          q    - Number of full quarters
          m    - Number of full months
          y    - Difference between day numbers
                 (eg 1st Jan 2004 is "1", the first day. 2nd Feb 2003 is "33". The datediff is "-32".)
          d    - Number of full days
          w    - Number of full weekdays
          ww   - Number of full weeks
          h    - Number of full hours
          n    - Number of full minutes
          s    - Number of full seconds (default)
          */
      /*Remove
          if (!$using_timestamps) {
              $datefrom = strtotime($datefrom, 0);
              $dateto   = strtotime($dateto, 0);
          }
      */
          // Auto-detect string date or int date:
          $dateto_str = strtotime($dateto);
          $datefrom_str = strtotime($datefrom);
          if ($dateto_str) $dateto = $dateto_str;
          if ($datefrom_str) $datefrom = $datefrom_str;
      
          $difference        = $dateto - $datefrom; // Difference in seconds
          $months_difference = 0;
      
          switch ($interval) {
              case 'yyyy': // Number of full years
                  $years_difference = floor($difference / 31536000);
                  if (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom), date("j", $datefrom), date("Y", $datefrom)+$years_difference) > $dateto) {
                      $years_difference--;
                  }
      
                  if (mktime(date("H", $dateto), date("i", $dateto), date("s", $dateto), date("n", $dateto), date("j", $dateto), date("Y", $dateto)-($years_difference+1)) > $datefrom) {
                      $years_difference++;
                  }
      
                  $datediff = $years_difference;
              break;
      
              case "q": // Number of full quarters
                  $quarters_difference = floor($difference / 8035200);
      
                  while (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom)+($quarters_difference*3), date("j", $dateto), date("Y", $datefrom)) < $dateto) {
                      $months_difference++;
                  }
      
                  $quarters_difference--;
                  $datediff = $quarters_difference;
              break;
      
              case "m": // Number of full months
                  $months_difference = floor($difference / 2678400);
      
                  while (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom)+($months_difference), date("j", $dateto), date("Y", $datefrom)) < $dateto) {
                      $months_difference++;
                  }
      
                  $months_difference--;
      
                  $datediff = $months_difference;
              break;
      
              case 'y': // Difference between day numbers
                  $datediff = date("z", $dateto) - date("z", $datefrom);
              break;
      
              case "d": // Number of full days
                  $datediff = floor($difference / 86400);
              break;
      
              case "w": // Number of full weekdays
                  $days_difference  = floor($difference / 86400);
                  $weeks_difference = floor($days_difference / 7); // Complete weeks
                  $first_day        = date("w", $datefrom);
                  $days_remainder   = floor($days_difference % 7);
                  $odd_days         = $first_day + $days_remainder; // Do we have a Saturday or Sunday in the remainder?
      
                  if ($odd_days > 7) { // Sunday
                      $days_remainder--;
                  }
      
                  if ($odd_days > 6) { // Saturday
                      $days_remainder--;
                  }
      
                  $datediff = ($weeks_difference * 5) + $days_remainder;
              break;
      
              case "ww": // Number of full weeks
                  $datediff = floor($difference / 604800);
              break;
      
              case "h": // Number of full hours
                  $datediff = floor($difference / 3600);
              break;
      
              case "n": // Number of full minutes
                  $datediff = floor($difference / 60);
              break;
      
              default: // Number of full seconds (default)
                  $datediff = $difference;
              break;
          }
      
          return $datediff;
      }
      ?>
      

      【讨论】:

        【解决方案7】:
            This will count a single day as one week and if you select sunday of one week and monday of another. though only 2 days are there but of different weeks therefore 2 weeks will be counted.
        
        
            Also works for different years
        
        
                function return_week($datee){
                    $duedt = explode("-", $datee);
                    $date  = mktime(0, 0, 0, $duedt[1], $duedt[2], $duedt[0]);
                    $week  = (int)date('W', $date);
                    return $week ;
        
                }
        
               function weeks_between($strtDate, $endDate){  
            // input dates of format yyyy-mm-dd between which you want to get number of weeks
            $start_date = DateTime::createFromFormat("Y-m-d", $strtDate);
            $end_date =  DateTime::createFromFormat("Y-m-d", $endDate);
            $start_year = $start_date->format("Y");
            $end_year = $end_date->format("Y");
            $start_month = $start_date->format("m");
            $end_month = $end_date->format("m");
            $week1  = return_week($strtDate);
            $week2  = return_week($endDate);
            $diff = $end_year - $start_year;;
            if($end_month<$start_month && $start_year!=$end_year ){
                $week_diff = (52*$diff-$week1)+$week2+1;
                return ($start_year==$end_year)?$week_diff:abs($week_diff);
            }else{
                $week_diff = $week2-$week1+1;
                return ($start_year==$end_year)?$week_diff:abs($week_diff)+52*$diff;
            }
        
        
            }
        
        //call to function
        weeks_between(""2018-10-21,"2019-10-21");
        

        【讨论】:

          【解决方案8】:
              $formt_start_date = new DateTime($start_date);
              $formt_end_date = new DateTime($end_date);
              for ($i = $formt_start_date; $i < $formt_end_date; $i->modify('+7 day')) {
                  $week_frequency[] = new DateTime($i->format("Y-m-d"));
          
              }
          

          【讨论】:

          • 虽然此代码可能会解决 OP 的问题,但最好添加上下文,或解释为什么这会解决 OP 的问题,以便将来的访问者可以从您的帖子中学习,并将这些知识应用于他们自己的问题。高质量的答案更有可能获得支持,并有助于提升 SO 作为平台的价值和质量。如果有帮助,您还可以添加文档链接。
          【解决方案9】:

          To check Full Code Click here

          PHP 中两个日期之间的所有星期数

          getNoOfWeek() 将返回第几周的数组。与年。您可以通过 week_text_alter() 更改此数组的格式。

          function getNoOfWeek($startDate, $endDate){
            // convert date in valid format
            $startDate = date("Y-m-d", strtotime($startDate));
            $endDate = date("Y-m-d", strtotime($endDate));
            $yearEndDay = 31;
            $weekArr = array();
            $startYear = date("Y", strtotime($startDate));
            $endYear = date("Y", strtotime($endDate));
          
            if($startYear != $endYear) {
              $newStartDate = $startDate;
          
              for($i = $startYear; $i <= $endYear; $i++) {
                if($endYear == $i) {
                  $newEndDate = $endDate;
                } else {
                  $newEndDate = $i."-12-".$yearEndDay;
                }
                $startWeek = date("W", strtotime($newStartDate));
                $endWeek = date("W", strtotime($newEndDate));
                if($endWeek == 1){
                  $endWeek = date("W", strtotime($i."-12-".($yearEndDay-7)));
                }
                $tempWeekArr = range($startWeek, $endWeek);
                array_walk($tempWeekArr, "week_text_alter", 
                   array('pre' => 'Week ', 'post' => " '". substr($i, 2, 2) ));
                $weekArr = array_merge($weekArr, $tempWeekArr);
          
                $newStartDate = date("Y-m-d", strtotime($newEndDate . "+1 days"));
              }
            } else {
              $startWeek = date("W", strtotime($startDate));
              $endWeek = date("W", strtotime($endDate));
              $endWeekMonth = date("m", strtotime($endDate));
              if($endWeek == 1 && $endWeekMonth == 12){
                $endWeek = date("W", strtotime($endYear."-12-".($yearEndDay-7)));
              }
              $weekArr = range($startWeek, $endWeek);
              array_walk($weekArr, "week_text_alter", 
                 array('pre' => 'Week ', 'post' => " '". substr($startYear, 2, 2)));
            }
            $weekArr = array_fill_keys($weekArr, 0);
            return $weekArr;
          }
          
          function week_text_alter(&$item1, $key, $prefix)
          {
            $item1 = $prefix['pre']. $item1 . $prefix['post'];
          }
          
          
          Output 1 -
          $weekArr = getNoOfWeek('2014-01-01', '2014-02-10');
          
          Array
          (
              [Week 1 '14] => 0
              [Week 2 '14] => 0
              [Week 3 '14] => 0
              [Week 4 '14] => 0
              [Week 5 '14] => 0
              [Week 6 '14] => 0
              [Week 7 '14] => 0
          )
          
          Output 2 -
          $weekArr = getNoOfWeek('2013-12-01', '2014-02-10');
          
          Array
          (
              [Week 48 '13] => 0
              [Week 49 '13] => 0
              [Week 50 '13] => 0
              [Week 51 '13] => 0
              [Week 52 '13] => 0
              [Week 1 '14] => 0
              [Week 2 '14] => 0
              [Week 3 '14] => 0
              [Week 4 '14] => 0
              [Week 5 '14] => 0
              [Week 6 '14] => 0
              [Week 7 '14] => 0
          )
          

          希望这会对你有所帮助。

          【讨论】:

            【解决方案10】:

            PHP 两个日期之间的周数问题

            以下是找出日期范围之间的周数的解决方案(针对帖子中提出的一个问题的更正解决方案 - https://stackoverflow.com/questions/27560850/php-number-of-week-between-2-dates-issue)。

            由于以下解决方案使用日期差异,因此必须使用 floor 函数包含开始日期周,并且必须使用包含结束日期周 ceil 然后它只返回正确的周数

            $strtDate = '2014-01-01';
            $endDate = '2015-03-17';
            
            $startDateWeekCnt = round(floor( date('d',strtotime($strtDate)) / 7)) ;
            // echo $startDateWeekCnt ."\n";
            $endDateWeekCnt = round(ceil( date('d',strtotime($endDate)) / 7)) ;
            //echo $endDateWeekCnt. "\n";
            
            $datediff = strtotime(date('Y-m',strtotime($endDate))."-01") - strtotime(date('Y-m',strtotime($strtDate))."-01");
            $totalnoOfWeek = round(floor($datediff/(60*60*24)) / 7) + $endDateWeekCnt - $startDateWeekCnt ;
            echo $totalnoOfWeek ."\n";
            

            【讨论】:

              猜你喜欢
              • 2015-09-15
              • 1970-01-01
              • 1970-01-01
              • 2021-10-16
              • 1970-01-01
              • 2012-04-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多