8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

PHP:在日期中添加月份,但不超过该月的最后一天

BK52 1月前

37 0

希望创建一个可以在 PHP 中执行此操作的函数。我需要将月份数添加到日期,但不能超过该月的最后一天。例如:将 1 个月添加到 1 月(...

希望创建一个可以在 PHP 中执行此操作的函数。

我需要向某个日期添加月份数,但不能超过该月的最后一天。

例如:

Add 1 month to January (1-28th), 2011, should produce February (1-28th), 2011.
Add 1 month to January 30th, 2011, should produce February 28th, 2011.
Add 3 months to January 31st, 2011, should produce April 30th, 2011.
Add 13 months to January 30th, 2011, should produce February 29th, 2012.
Add 1 month to October 31st, 2011, should produce November 30th, 2011.

如果我在 PHP 中使用日期加法,则会出现溢出:

Adding 1 month to January 30th, 2011, results in March 2nd, 2011.

我的规范不允许我超出新的月份。

实现这一目标的最简单的方法是什么?

帖子版权声明 1、本帖标题:PHP:在日期中添加月份,但不超过该月的最后一天
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由BK52在本站《datetime》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 你可以比较一下你添加一个月前后的月份日期。如果不一样,则说明你超出了下个月。

    function add($date_str, $months)
    {
        $date = new DateTime($date_str);
    
        // We extract the day of the month as $start_day
        $start_day = $date->format('j');
    
        // We add 1 month to the given date
        $date->modify("+{$months} month");
    
        // We extract the day of the month again so we can compare
        $end_day = $date->format('j');
    
        if ($start_day != $end_day)
        {
            // The day of the month isn't the same anymore, so we correct the date
            $date->modify('last day of last month');
        }
    
        return $date;
    }
    
    $result = add('2011-01-28', 1);   // 2011-02-28
    $result = add('2011-01-31', 3);   // 2011-04-30
    $result = add('2011-01-30', 13);  // 2012-02-29
    $result = add('2011-10-31', 1);   // 2011-11-30
    $result = add('2011-12-30', 1);   // 2011-02-28
    
  • 那么闰年呢?如果有人想从一个月的第一天添加一个月,会发生什么?如果我是对的:按照您的代码,在 1 月 1 日添加一个月会得到 1 月 30 日;在 2 月 1 日添加一个月会得到 3 月 3 日 - 不确定这是否是必要的,但如果是的话,这似乎不正确。

  • 这似乎对我有用,并给出了你想要的结果:

    <?php
    $date = "2011-01-30";
    
    list($year,$month,$day) = explode("-",$date);
    
    // add month here
    $month++;
    // to avoid a month-wrap, set the day to the number of days of the new month if it's too high
    $day = min($day,date("t",strtotime($year."-".$month."-01"))); 
    
    $date = $year."-".$month."-".$day;
    
    // 2011-02-28
    echo $date;
    ?>
    

    编辑:
    阅读了 Crend Kings 的评论后,我认为我们需要更多信息。在以下情况下期望的结果是什么:

    2011-01-30 > 2011-02-28 
    2011-01-28 > 2011-02-28 or 2011-02-26 ?
    2011-02-01 > 2011-03-01 or 2011-03-03 ?
    

    换句话说:该方法是否应该添加下个月的天数,这是 Crend King 所做的,并给出了像 2011-02-26 和 2011-03-03 这样的结果(这似乎不是我想要的结果)或者应该添加一个月并保留日期,而不是像我的代码那样添加一个“太高”的日期?我很困惑...

  • 2 月 28 日至 3 月 31 日怎么样?2 月 28 日至 4 月 30 日怎么样?

  • 我不认为这是规范的一部分...我认为我们需要更多的例子来理解这一点,请参阅我的编辑以获取更多信息

  • 如果 OP 只需要月份 +1(例如,添加(2 月 28 日)得到 3 月 28 日),我认为您的答案对于 1 个月的间隔是正确的。

  • @oezi 如果日期是 12 月,则此方法不起作用。例如:如果日期是 2011-12-30,则结果为 2011-13-30

  • erin 1月前 0 只看Ta
    引用 9

    据我所知,这个问题的范围非常有限,因此最好测试一种类型的错误并修复它。

    您要做的是确保在 29 日、30 日或 31 日等较晚的日期上添加“一个月”不会将您推到下个月的 1 日、2 日或 3 日。

    date_modify() 的工作方式(将其用于示例日期 \'2012-01-31\',并带有类似 \'+1 months\' 的字符串)是,它首先将月份数增加 1,然后从该月份的开始处查找第 31 天。这就是它溢出到 3 月 3 日的原因。

    如果这不是您想要的,您所要做的就是再次使用 date_modify(),现在告诉它回溯几天(本例中为 3 天)。由于您只想回到上个月的最后一天,因此您想要回溯的天数始终与错误日期中的日期相同。

    剩下的就是确保不要在不需要时应用此修正,例如当 PHP 将来改进时。这相对容易,因为可能出现问题的情况范围非常有限。

    • (1)此问题仅在 向日期 29、30 或 31
    • (2)当问题发生时,得到的日期总是1、2或3。

    下面的代码添加了“+1 个月”,检查这是否导致月份中的日期从高位大幅变化到低位,如果是的话则调整日期。

    //Create the date, store its day-of-month, and add X months
    $myDateTimeISO = "2012-01-31";
    $addThese = 1;
    $myDateTime = new DateTime($myDateTimeISO);
    $myDayOfMonth = date_format($myDateTime,'j');
    date_modify($myDateTime,"+$addThese months");
    
    //Find out if the day-of-month has dropped
    $myNewDayOfMonth = date_format($myDateTime,'j');
    if ($myDayOfMonth > 28 && $myNewDayOfMonth < 4){
    //If so, fix by going back the number of days that have spilled over
        date_modify($myDateTime,"-$myNewDayOfMonth days");
    }
    echo date_format($myDateTime,"Y-m-d");
    

    结果是:2012-02-29(是的,这是闰年)。

    PS:如果您想添加年份,问题和症状几乎相同。同样,您只需要检查结果中的日期是否为 1/2/3,而输入的日期是否为 29/30/31。如果是这样,您需要使用 date_modify 返回 \'-X 天\',其中 X 是结果中的日期。

  • 您可以使用此代码。第一行接受任何格式的日期,后面的几行拆分月份值,添加月份并返回 Y-M-D 格式的最终​​值。

    $year_month = Date("Y-m", strtotime($date));
    $year_month_incremented = Date("Y-m", strtotime($year_month . " +1 Month "));
    $month_end_dt =strtotime('last day of this month', strtotime($year_month_incremented));
    $date = date('Y-m-d', $month_end_dt );
    
  • 如果将开始日期设置为 $date = '2020-01-01' 则结果将是 2020-02-29?

  • 引用 12

    对于任何感兴趣的人,我都提出了一个可靠的方法来处理这个问题

    /**
     * @var \DateInterval
     */
    private $remainder;
    
    /**
     * @param \DateTimeImmutable $date
     * @param string $modifier
     * @return \DateTimeImmutable
     */
    private function nextInterval(\DateTimeImmutable $date, $modifier)
    {
        $dayNumber = (int)$date->format('j');
        $next = $date->modify($modifier);
        if (!is_null($this->remainder)) {
            $next = $next->add($this->remainder);
            $dayNumber += $this->remainder->days;
            $this->remainder = null;
        }
    
        // This should in general only apply to months which do not have the same daynumber in that month after adding
        if ($dayNumber !== (int)$next->format('j')) {
            $n = $next->modify('last day of last month');
            $this->remainder = $n->diff($next);
            $next = $n;
        }
    
        return $next;
    }
    

    结果:

    2014-11-30
    2014-12-30
    2015-01-30
    2015-02-28
    2015-03-30
    2015-04-30
    2015-05-30
    

    2015-12-30
    2016-01-30
    2016-02-29
    2016-03-30
    2016-04-30
    
  • 您也可以使用此代码。

    <?php
    $monthToAdd = 1;
    
    $d1 = DateTime::createFromFormat('Y-m-d H:i:s', '2011-01-30 15:57:57');
    
    $year = $d1->format('Y');
    $month = $d1->format('n');
    $day = $d1->format('d');
    
    $year += floor($monthToAdd/12);
    $monthToAdd = $monthToAdd%12;
    $month += $monthToAdd;
    if($month > 12) {
        $year ++;
        $month = $month % 12;
        if($month === 0)
            $month = 12;
    }
    
    if(!checkdate($month, $day, $year)) {
        $d2 = DateTime::createFromFormat('Y-n-j', $year.'-'.$month.'-1');
        $d2->modify('last day of');
    }else {
        $d2 = DateTime::createFromFormat('Y-n-d', $year.'-'.$month.'-'.$day);
    }
    $d2->setTime($d1->format('H'), $d1->format('i'), $d1->format('s'));
    echo $d2->format('Y-m-d H:i:s');
    
  • // 我已经更新了获取月份最后日期的逻辑

    function addMonthGetLastDate($date_str, $months)
    {
        
       
        list($year,$month,$day) = explode("-",$date_str);
        // add month here
        $month += ($months-1);
        if($month>12)
        {
            $month = $month - 12;
            $year += 1;
        }
        // to avoid a month-wrap, set the day to the number of days of the new month if it's too high
        $day = min($day,date("t",strtotime($year."-".$month.".01."))); 
        $date = date('Y-m-t', strtotime($year."-".$month."-".$day));
        
        return $date;
    }
    
返回
作者最近主题: