【问题标题】:How to get every month number and year between two month/year points如何获得两个月/年点之间的每个月数和年份
【发布时间】:2020-12-08 00:02:35
【问题描述】:

我正在创建一个函数,您可以在其中给出起始年份、月份和结束年份、月份,该函数将在两个给定点之间打印每个月和年。

我已经创建了一个完美运行的函数,但我认为这不是一个好的做法,可能有更好的方法来做到这一点。现在我正在寻求您的帮助以找到更好的方法。

附:我无法获得完整日期作为输入。只能获取月份和年份。

这是我的代码 -

function get_all_months($monthstart = null, $yearstart = null, $monthend = null, $yearend = null) {
if (($monthstart === null) || ($yearstart === null) || ($monthend === null) || ($yearend === null)) {
    $monthend = date('m');
    $yearend = date('Y');
    if($monthend < 6) {
        $yearstart = $yearend - 1;
        $monthstart = (($monthend - 5) + 12);
    } else {
        $yearstart = $yearend;
        $monthstart = $monthend - 5;
    }
}
$month_array = array();
if ($yearstart > $yearend) {
    for ($m=$monthend; $m<=12; $m++) $month_array[] = array('month' => $m, 'year' => $yearend);
    for ($y=$yearend+1; $y<$yearstart; $y++) for ($m=1; $m<=12; $m++) $month_array[] = array('month' => $m, 'year' => $y);
    for ($m=1; $m<=$monthstart; $m++) $month_array[] = array('month' => $m, 'year' => $yearstart);
} elseif ($yearend > $yearstart) {
    for ($m=$monthstart; $m<=12; $m++) $month_array[] = array('month' => $m, 'year' => $yearstart);
    for ($y=$yearstart+1; $y<$yearend; $y++) for ($m=1; $m<=12; $m++) $month_array[] = array('month' => $m, 'year' => $y);
    for ($m=1; $m<=$monthend; $m++) $month_array[] = array('month' => $m, 'year' => $yearend);
} else {
    for ($m=$monthstart; $m<=$monthend; $m++) $month_array[] = array('month' => $m, 'year' => $yearstart);
}
return $month_array;
}

编辑:根据 Nigel Ren 的回答,这是我能想到的最佳方式 -

 function get_all_months($monthstart = null, $yearstart = null, $monthend = null, $yearend = null) {

if (($monthstart === null) || ($yearstart === null) || ($monthend === null) || ($yearend === null)) {
    $monthend = date('m');
    $yearend = date('Y');
    if($monthend < 6) {
        $yearstart = $yearend - 1;
        $monthstart = (($monthend - 5) + 12);
    } else {
        $yearstart = $yearend;
        $monthstart = $monthend - 5;
    }
}

$output = [];

if ($yearstart > $yearend) {
    $time   = strtotime($yearend."-".$monthend);
    $last   = date('m-Y', strtotime($yearstart."-".$monthstart));
} else {
    $time   = strtotime($yearstart."-".$monthstart);
    $last   = date('m-Y', strtotime($yearend."-".$monthend));
}
do {
        $cur_month_year = date('m-Y', $time);
        $month = date('m', $time);
        $year = date('Y', $time);
        $output[] =  array('month'=>$month,'year'=>$year);
        $time = strtotime('+1 month', $time);
    }
    while ($cur_month_year != $last);
    return $output;
}

【问题讨论】:

标签: php


【解决方案1】:

使用DateTime类和DateInterval,可以创建指定范围的DateTime对象generator

<?php

function get_all_months(int $monthstart, int $yearstart, int $monthend, int $yearend) {
        $onemonth = new DateInterval('P1M'); // one month interval
        $timeperiod = new DatePeriod(
                DateTime::createFromFormat('Y-m', "{$yearstart}-{$monthstart}"),
                $onemonth,
                DateTime::createFromFormat('Y-m', "{$yearend}-{$monthend}")->add($onemonth)
        );
        foreach ($timeperiod as $pos) {
                yield clone $pos;
        }
}

foreach (get_all_months(12, 2009, 1, 2020) as $month) {
        echo "{$month->format('Y-m')}\n";
}

DateTime 应该比纯字符串或数字数组更灵活(请参阅DateTime::format 了解更多使用选项)。


注意:受@keidakida 启发,更新了我的答案。

【讨论】:

    【解决方案2】:

    您可以使用用于这些目的的 PHP 的 DateInterval 类。试试这个代码

    <?php
    function getMonthsFromRange($start, $end, $format = 'M Y')
    {
    
        $array = array();
    
        // Since you wanted 1 month it is Period = 1 Month
        $interval = new DateInterval('P1M');
    
        $realEnd = new DateTime($end);
        $realEnd->add($interval);
    
        $period = new DatePeriod(new DateTime($start), $interval, $realEnd);
    
        // Use loop to store date into array 
        foreach ($period as $date)
            $array[] = $date->format($format);
    
        // Return the array elements 
        return $array;
    }
    
    // Function call with passing the start date and end date 
    $months = getMonthsFromRange('2010-10', '2011-11');
    
    print_r($months);
    

    它的输出是:

    Array ( [0] => Oct 2010 [1] => Nov 2010 [2] => Dec 2010 [3] => Jan 2011 [4] => Feb 2011 [5] => Mar 2011 [6] => Apr 2011 [7] => May 2011 [8] => Jun 2011 [9] => Jul 2011 [10] => Aug 2011 [11] => Sep 2011 [12] => Oct 2011 [13] => Nov 2011 )
    

    【讨论】:

      【解决方案3】:

      根据答案here,只需将开始日期添加1个月,直到您到达结束日期...

      function get_all_months($monthstart = null, $yearstart = null, $monthend = null, $yearend = null) {
          $output = [];
          $time   = strtotime($yearstart."-".$monthstart);
          $last   = date('m-Y', strtotime($yearend."-".$monthend));
          do {
              $month = date('m-Y', $time);
              $output[] =  $month;
              $time = strtotime('+1 month', $time);
          }
          while ($month != $last);
          return $output;
      }
      

      所以

      print_r(get_all_months(4,2008,2,2010));
      

      给...

      Array
      (
          [0] => 04-2008
          [1] => 05-2008
          [2] => 06-2008
          [3] => 07-2008
          [4] => 08-2008
          [5] => 09-2008
          [6] => 10-2008
          [7] => 11-2008
          [8] => 12-2008
          [9] => 01-2009
          [10] => 02-2009
          [11] => 03-2009
          [12] => 04-2009
          [13] => 05-2009
          [14] => 06-2009
          [15] => 07-2009
          [16] => 08-2009
          [17] => 09-2009
          [18] => 10-2009
          [19] => 11-2009
          [20] => 12-2009
          [21] => 01-2010
          [22] => 02-2010
      )
      

      【讨论】:

        【解决方案4】:

        如果我理解正确 - 你得到的月份是一个数字,年份是一个数字,例如 6 和 1997。如果我们假设开始年份总是小于结束年份,我建议这样做。

        function distanceBetweenDates(int $sm, int $sy, int $em, int $ey) {
            $monthsBetweenYears = ($ey - $sy + 1) * 12;
            $distanceBetweenMonths = $monthsBetweenYears - $sm - (12 - $em);
            
            $startMonth = $sm + 1;
            $startYear = $sy;
            
            while ($distanceBetweenMonths > 0) {
                if ($startMonth <= 12) {
                    echo $startMonth . ' - ' . $startYear;
                } else {
                    $startMonth = 1;
                    $startYear++;
                    echo $startMonth . ' - ' . $startYear;
                }
                echo "\n";
                $startMonth++;
                $distanceBetweenMonths--;
            }
        }
        

        您可能需要查看的唯一内容是计算中是否包含或排除给定月份。

        这里唯一缺少的是验证,因为如果你在方法中使用类型,它可以被“跳过”。

        【讨论】:

          【解决方案5】:

          您可能正在寻找这样的东西:

          function get_all_months($monthstart = null, $yearstart = null, $monthend = null, $yearend = null) {
              $month_array = [];
              if ($yearstart == $yearend)
                  for ($m=$monthstart; $m<=$monthend; $m++) $month_array[] = array('month' => $m, 'year' => $yearstart);
              else {
                  for ($m=$monthstart; $m<=12; $m++) $month_array[] = array('month' => $m, 'year' => $yearstart);
                  for ($y=$yearstart+1; $y<$yearend; $y++) for ($m=1; $m<=12; $m++) $month_array[] = array('month' => $m, 'year' => $y);
                  for ($m=1; $m<=$monthend; $m++) $month_array[] = array('month' => $m, 'year' => $yearend);
              }
              return $month_array;
          }
          

          【讨论】:

          • 同样的事情,我的代码几乎没有 if else 来确保即使是 null 输入也能提供最后 6 个月,并且如果结束/开始年份被切换,它不应该中断。
          • 我在这方面做了一点工作,并且能够大大减少代码
          • @b0xed 如果您需要支持反转值 - 只需在循环之前交换 yearstart/end 中的值
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-01-19
          • 1970-01-01
          • 1970-01-01
          • 2019-05-15
          • 2020-08-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多