【问题标题】:Find Month difference in php? [duplicate]在php中查找月份差异? [复制]
【发布时间】:2023-04-04 20:30:01
【问题描述】:

有什么方法可以在 PHP 中找到月差?我有从 2003 年 10 月 17 日到 2004 年 3 月 24 日的输入。我需要找出这两天内有多少个月。假设如果 6 个月,我只需要几个月的输出。感谢您为我提供日差指导。

我通过 MySQL 找到了解决方案,但我需要它在 PHP 中。任何人都可以帮助我,提前谢谢。

【问题讨论】:

标签: php datetime date


【解决方案1】:

无需重新发明轮子的最简单方法。这将为您提供完整个月的差异。 IE。以下两个日期相差几乎 76 个月,但结果是 75 个月。

date_default_timezone_set('Asia/Tokyo');  // you are required to set a timezone

$date1 = new DateTime('2009-08-12');
$date2 = new DateTime('2003-04-14');

$diff = $date1->diff($date2);

echo (($diff->format('%y') * 12) + $diff->format('%m')) . " full months difference";

【讨论】:

  • 伟大的工作:只是一个小问题,如何获得使用天数?
  • @noobie 请RTFM for DateInterval::format 查找所有可能的格式选项。
  • 奇怪的结果:从:2013-03-01,直到:2013-04-01,差异年份:0,差异月份:1,差异天数:3。少于 31 天的月份也给出月差=0
  • 谨慎使用! 01.01.2013 和 31.03.2013 之间的月差将是 2 个月(不是预期的 3 个月!)
  • @ValentinDespa 实际上 01.01.2013 和 31.03.2013 之间的差异是 2 months and 30 days,这是准确的。如果您预计正好相差 3 个月,您将是一个乐观的人 :-)
【解决方案2】:

在测试大量解决方案后,将所有解决方案都放入单元测试中,这就是我得出的结论:

/**
 * Calculate the difference in months between two dates (v1 / 18.11.2013)
 *
 * @param \DateTime $date1
 * @param \DateTime $date2
 * @return int
 */
public static function diffInMonths(\DateTime $date1, \DateTime $date2)
{
    $diff =  $date1->diff($date2);

    $months = $diff->y * 12 + $diff->m + $diff->d / 30;

    return (int) round($months);
}

例如它将返回(来自单元测试的测试用例):

  • 01.11.2013 - 30.11.2013 - 1 个月
  • 01.01.2013 - 31.12.2013 - 12 个月
  • 31.01.2011 - 28.02.2011 - 1 个月
  • 01.09.2009 - 01.05.2010 - 8 个月
  • 01.01.2013 - 31.03.2013 - 3 个月
  • 15.02.2013 - 15.04.2013 - 2 个月
  • 01.02.1985 - 31.12.2013 - 347 个月

注意:由于它是按天四舍五入的,即使是半个月也会被四舍五入,如果你在某些情况下使用它可能会导致问题。所以不要在这种情况下使用它,它会导致你的问题。

例如:

  • 02.11.2013 - 31.12.2013 将返回 2,而不是 1(如预期的那样)。

【讨论】:

  • 不错的解决方案,例如 01.06 - 01.07 给出 0 个月(以 m 为单位),但使用天数和舍入它可以正常工作
  • 非常好的解决方案。
【解决方案3】:

如果有人正在寻找一个简单的解决方案来计算每个涉及的月份而不是完整的月份、四舍五入的月份或类似的东西,我只是想添加这个。

// Build example data
$timeStart = strtotime("2003-10-17");
$timeEnd = strtotime("2004-03-24");
// Adding current month + all months in each passed year
$numMonths = 1 + (date("Y",$timeEnd)-date("Y",$timeStart))*12;
// Add/subtract month difference
$numMonths += date("m",$timeEnd)-date("m",$timeStart);

echo $numMonths;

【讨论】:

    【解决方案4】:

    哇,想太多问题了……这个版本怎么样:

    function monthsBetween($startDate, $endDate) {
        $retval = "";
    
        // Assume YYYY-mm-dd - as is common MYSQL format
        $splitStart = explode('-', $startDate);
        $splitEnd = explode('-', $endDate);
    
        if (is_array($splitStart) && is_array($splitEnd)) {
            $difYears = $splitEnd[0] - $splitStart[0];
            $difMonths = $splitEnd[1] - $splitStart[1];
            $difDays = $splitEnd[2] - $splitStart[2];
    
            $retval = ($difDays > 0) ? $difMonths : $difMonths - 1;
            $retval += $difYears * 12;
        }
        return $retval;
    }
    

    注意:与其他几个解决方案不同,这不依赖于 PHP 5.3 中添加的日期函数,因为许多共享主机还没有。

    【讨论】:

    • 我刚刚将这一行 $retval = ($difDays > 0) ? $difMonths : $difMonths - 1; 编辑为 $retval = ($difDays >= 0) ? $difMonths : $difMonths - 1; 所以 2017-02-01 和 2017-03-01 之间的差异只有 1
    【解决方案5】:

    http://www.php.net/manual/en/datetime.diff.php

    这将返回一个具有格式方法的 DateInterval 对象。

    【讨论】:

      【解决方案6】:
      $datetime1 = date_create('2009-10-11');
      
      $datetime2 = date_create('2013-1-13');
      
      $interval = date_diff($datetime1, $datetime2);
      
      echo $interval->format('%a day %m month %y year');
      

      【讨论】:

      • php 中的日月年差异
      • 您好,请解释一下为什么这是一个解决方案。谢谢
      【解决方案7】:
      function monthsDif($start, $end)
      {
          // Assume YYYY-mm-dd - as is common MYSQL format
          $splitStart = explode('-', $start);
          $splitEnd = explode('-', $end);
      
          if (is_array($splitStart) && is_array($splitEnd)) {
              $startYear = $splitStart[0];
              $startMonth = $splitStart[1];
              $endYear = $splitEnd[0];
              $endMonth = $splitEnd[1];
      
              $difYears = $endYear - $startYear;
              $difMonth = $endMonth - $startMonth;
      
              if (0 == $difYears && 0 == $difMonth) { // month and year are same
                  return 0;
              }
              else if (0 == $difYears && $difMonth > 0) { // same year, dif months
                  return $difMonth;
              }
              else if (1 == $difYears) {
                  $startToEnd = 13 - $startMonth; // months remaining in start year(13 to include final month
                  return ($startToEnd + $endMonth); // above + end month date
              }
              else if ($difYears > 1) {
                  $startToEnd = 13 - $startMonth; // months remaining in start year 
                  $yearsRemaing = $difYears - 2;  // minus the years of the start and the end year
                  $remainingMonths = 12 * $yearsRemaing; // tally up remaining months
                  $totalMonths = $startToEnd + $remainingMonths + $endMonth; // Monthsleft + full years in between + months of last year
                  return $totalMonths;
              }
          }
          else {
              return false;
          }
      }
      

      【讨论】:

      • 已修正 - 更改 $startToEnd = 12 - $startMonth;到 $startToEnd = 13 - $startMonth;和以前一样,它没有计算 12 月的持续时间
      【解决方案8】:
      // get year and month difference
      
      $a1 = '20170401';
      
      $a2 = '20160101'
      
      $yearDiff = (substr($a1, 0, 4) - substr($a2, 0, 4));
      
      $monthDiff = (substr($a1, 4, 2) - substr($a2, 4, 2));
      
      $fullMonthDiff = ($yearDiff * 12) + $monthDiff;
      
      // fullMonthDiff = 16
      

      【讨论】:

        【解决方案9】:

        这是我的增强版@deceze 答案:

         /**
         * @param string $startDate
         * Current date is considered if empty string is passed
         * @param string $endDate
         * Current date is considered if empty string is passed
         * @param bool $unsigned
         * If $unsigned is true, difference is always positive, otherwise the difference might be negative
         * @return int
         */
        public static function diffInFullMonths($startDate, $endDate, $unsigned = false)
        {
            $diff = (new DateTime($startDate))->diff(new DateTime($endDate));
            $reverse = $unsigned === true ? '' : '%r';
            return ((int) $diff->format("{$reverse}%y") * 12) + ((int) $diff->format("{$reverse}%m"));
        }
        

        【讨论】:

          【解决方案10】:

          最好的方法。

          function getIntervals(DateTime $from, DateTime $to)
          {
              $intervals = [];
              $startDate = $from->modify('first day of this month');
              $endDate = $to->modify('last day of this month');
              while($startDate < $endDate){
                  $firstDay = $startDate->format('Y-m-d H:i:s');
                  $startDate->modify('last day of this month')->modify('+1 day');
                  $intervals[] = [
                      'firstDay' => $firstDay,
                      'lastDay' => $startDate->modify('-1 second')->format('Y-m-d H:i:s'),
                  ];
                  $startDate->modify('+1 second');
              }
              return $intervals;
          }
          $dateTimeFirst = new \DateTime('2013-01-01');
          $dateTimeSecond = new \DateTime('2013-03-31');
          $interval = getIntervals($dateTimeFirst, $dateTimeSecond);
          print_r($interval);
          

          结果:

          Array
          (
              [0] => Array
                  (
                      [firstDay] => 2013-01-01 00:00:00
                      [lastDay] => 2013-01-31 23:59:59
                  )
          
              [1] => Array
                  (
                      [firstDay] => 2013-02-01 00:00:00
                      [lastDay] => 2013-02-28 23:59:59
                  )
          
              [2] => Array
                  (
                      [firstDay] => 2013-03-01 00:00:00
                      [lastDay] => 2013-03-31 23:59:59
                  )
          
          )
          

          【讨论】:

            【解决方案11】:

            在我的情况下,我还需要计算整月和一天的剩余时间以及构建折线图标签。

            /**
             * Calculate the difference in months between two dates
             *
             * @param \DateTime $from
             * @param \DateTime $to
             * @return int
             */
            public static function diffInMonths(\DateTime $from, \DateTime $to)
            {
                // Count months from year and month diff
                $diff = $to->diff($from)->format('%y') * 12 + $to->diff($from)->format('%m');
            
                // If there is some day leftover, count it as the full month
                if ($to->diff($from)->format('%d') > 0) $diff++;
            
                // The month count isn't still right in some cases. This covers it.
                if ($from->format('d') >= $to->format('d')) $diff++;
            }
            

            【讨论】:

              【解决方案12】:
              <?php
                # end date is 2008 Oct. 11 00:00:00
                $_endDate = mktime(0,0,0,11,10,2008);
                # begin date is 2007 May 31 13:26:26
                $_beginDate = mktime(13,26,26,05,31,2007);
              
                $timestamp_diff= $_endDate-$_beginDate +1 ;
                # how many days between those two date
                $days_diff = $timestamp_diff/2635200;
              
              ?>
              

              参考:http://au.php.net/manual/en/function.mktime.php#86916

              【讨论】:

              • 和@Kai的解决方法一样的问题,很乐观的假设一个月有30天……
              【解决方案13】:

              这是一个快速的:

              $date1 = mktime(0,0,0,10,0,2003); // m d y, use 0 for day
              $date2 = mktime(0,0,0,3,0,2004); // m d y, use 0 for day
              
              echo round(($date2-$date1) / 60 / 60 / 24 / 30);
              

              【讨论】:

              • 这将变得越来越不准确,这两个日期相距越远,最终可能会以错误的方式四舍五入......
              • 如果月份有31 days 以防January, March, May, July, August, October, December28 days 以防February 会发生什么,因为你除以30。
              猜你喜欢
              • 1970-01-01
              • 2013-09-11
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-08-17
              相关资源
              最近更新 更多