下个月,PHP当天

时间:2009-06-05 22:02:05

标签: php algorithm datetime

我有一个“活动”,需要在每个月的同一天安排。

假设您在5月1日设置开始日期,您应该在6月1日,7月1日等下一个事件。问题出现在31日的开始日期(下一个可能是30或28取决于这个月)。

考虑到有几个月有不同的天数(28,30,31),取决于月份本身和年份......什么是一种简单的方法来设置它?

考虑以下(和有缺陷的)nextmonth函数:

$events = array()

function nextmonth($date) {
   return $date+(60*60*24*30);
}
$curr = $start;
while($curr < $end) {
    $events[ = $curr;
    $curr = nextmonth($curr);
}

编辑补充说:对我来说,问题是,如何解决任何给定月份的天数,从而得到下一个相应的日期。

16 个答案:

答案 0 :(得分:9)

<强>更新

这将为您提供给定月份的天数:

echo date('t', $timestamp);

请参阅:date()

旧回答:

我不确定您正在考虑的算法,但我相信这会对您有所帮助:

echo date('d-M-y', strtotime('next month'));

答案 1 :(得分:5)

这将提前提供$ X个月的正确时间戳:mktime(0,0,0,date("m")+$X,date('d'),date("Y"));

答案 2 :(得分:3)

试试这个。 reday是补充日期(int - day)。如果少于今天,它将在本月给出reday但不会超过。这个月的日子。如果今天超过今天给reday下个月相同的条件。我用它来计算每月补充点的“下一次补充”。返回dd/mm/yyyy

function nextrefill($reday) {
    if (date("j") < $reday) {
        $numd = date("t");
        if ($reday > $numd) {
            return str_pad($numd, 2, "0", STR_PAD_LEFT).date("/m/Y");
        } else {
            return str_pad($reday, 2, "0", STR_PAD_LEFT).date("/m/Y");
        }
    } else {
        $nextm = date('m', strtotime('first day of next month'));
        $nextmy = date('Y', strtotime('first day of next month'));
        $numd = cal_days_in_month(CAL_GREGORIAN, $nextm, $nextmy);
        if ($reday > $numd) {
            return str_pad($numd, 2, "0", STR_PAD_LEFT)."/".$nextm."/".$nextmy;
        } else {
            return str_pad($reday, 2, "0", STR_PAD_LEFT)."/".$nextm."/".$nextmy;
        }
    }
}

更直接指向(编辑)

function nextmonthday($day) {
        $next_month = date('m', strtotime('first day of next month'));
        $year_of_next_month = date('Y', strtotime('first day of next month'));
        $no_of_day_in_next_month = cal_days_in_month(CAL_GREGORIAN, $nextm, $nextmy);
        if ($day > $no_of_day_in_next_month){
            return str_pad($no_of_day_in_next_month, 2, "0", STR_PAD_LEFT)."/".$next_month."/".$year_of_next_month;
        } else {
            return str_pad($day, 2, "0", STR_PAD_LEFT)."/".$next_month."/".$year_of_next_month;
        }
}

答案 3 :(得分:2)

我建议在php.net上阅读以下评论。 strtotime() (php.net)

编辑:下一个答案给出了我为那些无法破译那里显示内容的人发布的链接的“摘要”。

答案 4 :(得分:1)

由于月份的大小各不相同,下个月设置的最佳方式不是:下个月的这一天,除非下个月不存在这一天。

示例:

June 5, 2009, next month would be July 5, 2009
August 31, 2009, next month would be September 30, 2009

或简称为strtotime("+1 month")

答案 5 :(得分:1)

将此视为百灵鸟,它确实有效

strtotime('last day next month')

所以:

$today_next_month = strtotime('this day next month');
$last_day_next_month = strtotime('last day next month');
if (date('d', $today_next_month) < date('d', $last_day_next_month)){
    $date = date('m-d-Y', $last_day_next_month); 
} else {
    $date = date('m-d-Y', $today_next_month);
}
echo "And the winner is : $date<br/>";

答案 6 :(得分:1)

简单

public function adicionarMesMantendoDia($date, $months, $format = "Y-m-d"){
        $date = \DateTime::createFromFormat($format, $date);

        for($i=0;$i < $months; $i++){
            $date->modify('+ ' . date("t", $date->getTimestamp())  . ' day');
        }
        return $date;
}

答案 7 :(得分:1)

以上都没有照顾过非现有日子(例如2月30日或4月31日),所以这是我的功能:

<?php
function getSameDayNextMonth($time, $numberMonthsToAdd = 1)
{
    list($year, $month, $day) = explode('-', date("Y-m-d", $time));

    // replace the day by one temporarily (just to make sure it exists for any month
    $numberOfYearsToAdd = floor($numberMonthsToAdd / 12);
    $year += $numberOfYearsToAdd;
    $month = ($month + $numberMonthsToAdd) % 12;
    if (0 === $month) {
        $month = 12;
    }
    $monthFormatted = sprintf('%02s', $month);
    $nbDaysInThisMonth = date("t", strtotime("$year-$monthFormatted-01"));

    if ((int)$day > $nbDaysInThisMonth) {
        $day = $nbDaysInThisMonth;
    }
    $day = sprintf('%02s', $day);
    return strtotime("$year-$monthFormatted-$day");
}


$time = strtotime("2017-10-31");
for ($i = 0; $i <= 15; $i++) {
    $_time = getSameDayNextMonth($time, $i);
    echo date("Y-m-d", $_time) . '<br>';
}

/**
 * 2017-10-31
 * 2017-11-30
 * 2017-12-31
 * 2017-01-31
 * 2017-02-28
 * 2017-03-31
 * 2017-04-30
 * 2017-05-31
 * 2017-06-30
 * 2017-07-31
 * 2017-08-31
 * 2017-09-30
 * 2018-10-31
 * 2018-11-30
 * 2018-12-31
 * 2018-01-31
 */

答案 8 :(得分:1)

很多时间过去但是如果有人正在搜索这个,在上面的所有答案中我发现只有@ling答案实际上回答了这个问题,但他的答案仍然不是100%准确,它输出年份部分不正确正如你在上面的结果中看到的那样。

以下是修复年份问题的代码的修改版本(我也将其修改为使用DateTime类)

  /**
   * Adding month in PHP using DateTime
   * class will render the date in a way that
   * we do not desire, for example adding one month
   * to 2018-01-31 will result in 2018-03-03 but
   * we want it to be 2018-02-28 instead.
   *
   * This method ensure that adding months
   * to a date get caculated properly.
   *
   *
   * @param DateTime $startDate
   * @param int $numberOfMonthsToAdd
   *
   * @return DateTime
   */
  function getSameDayNextMonth(DateTime $startDate, $numberOfMonthsToAdd = 1) {
    $startDateDay = (int) $startDate->format('j');
    $startDateMonth = (int) $startDate->format('n');
    $startDateYear = (int) $startDate->format('Y');

    $numberOfYearsToAdd = floor(($startDateMonth + $numberOfMonthsToAdd) / 12);
    if ((($startDateMonth + $numberOfMonthsToAdd) % 12) === 0) {
      $numberOfYearsToAdd--;
    }
    $year = $startDateYear + $numberOfYearsToAdd;

    $month = ($startDateMonth + $numberOfMonthsToAdd) % 12;
    if ($month === 0) {
      $month = 12;
    }
    $month = sprintf('%02s', $month);

    $numberOfDaysInMonth = (new DateTime("$year-$month-01"))->format('t');
    $day = $startDateDay;
    if ($startDateDay > $numberOfDaysInMonth) {
      $day = $numberOfDaysInMonth;
    }
    $day = sprintf('%02s', $day);

    return new DateTime("$year-$month-$day");
  }


  // Quick Test
  $startDate = new DateTime('2018-01-31');
  for($i=0; $i <= 40; $i++) {
    echo getSameDayNextMonth($startDate, $i)->format('Y-m-d') . "\n";
  }

输出:

2018-01-31
2018-02-28
2018-03-31
2018-04-30
2018-05-31
2018-06-30
2018-07-31
2018-08-31
2018-09-30
2018-10-31
2018-11-30
2018-12-31
2019-01-31
2019-02-28
2019-03-31
2019-04-30
2019-05-31
2019-06-30
2019-07-31
2019-08-31
2019-09-30
2019-10-31
2019-11-30
2019-12-31
2020-01-31
2020-02-29
2020-03-31
2020-04-30
2020-05-31
2020-06-30
2020-07-31
2020-08-31
2020-09-30
2020-10-31
2020-11-30
2020-12-31
2021-01-31
2021-02-28
2021-03-31
2021-04-30
2021-05-31

答案 9 :(得分:0)

这个功能怎么样:

    function getNextMonthN($date, $n = 1) {
      $newDate = strtotime('+' . $n . ' months', $date);
      if (date('j', $date) !== (date('j', $newDate))) {
        $newDate = mktime(0, 0, 0, date('n', $newDate), 0, date('Y', $newDate));
      }
      return $newDate;  
    }

comments的strtotime条目下,php.net手册网站上还有另一个解决方案。

答案 10 :(得分:0)

没有人提到这个替代方案,虽然结果和其他人一样,可能不是OP想要的:

$today = new DateTime();
$today->modify("+1 month");
echo $today->format("d.m.Y");

为什么不分别存储月份和日期并逐月增加,然后使用PHP的checkdate函数验证日期,将日期减1,直到日期有效?

答案 11 :(得分:0)

我知道这是一篇很老的帖子,但我想提出一个不同的方法。

因此,不要试图找出一个月内的日子(这有点复杂),而是可以轻松找出下个月使用当月,例如:

date("m", strtotime($current."+1 month"));

然后使用date("d")获取当月的当天,并在上个代码中与下个月联系。

答案 12 :(得分:0)

我也有同样的问题,但是当我尝试上面的解决方案时,他们无法完美地为我工作,我尝试了我的最终并提出了新的解决方案:

$startDate = date("Y-m-d");
$month = date("m",strtotime($startDate));
$nextmonth = date("m",strtotime("$startDate +1 month"));
if((($nextmonth-$month) > 1) || ($month == 12 && $nextmonth != 1))
{
    $nextDate = date( 't.m.Y',strtotime("$startDate +1 week"));
}else
{
    $nextDate = date("Y-m-d",strtotime("$startDate +1 month"));
}
echo $nextSameDate = date("Y",$nextDate).'-'.date("m",$nextDate).'-'.date("d",$startDate);

答案 13 :(得分:0)

日期时间OOP样式

<?php
//Start Date -> 18-09-2015
$expiry = new DateTime();
for($i=1;$i<5;$i++){
   $expiry->modify('+1 Month');
   echo $expiry->format('d-m-Y');
   echo '<br>';
}
?>

//18-10-2015
//18-11-2015
//18-12-2015
//18-01-2016

答案 14 :(得分:0)

我创建了一个名为my_strtotime的函数,它将处理加减月数。它基本上是strtotime的包装。

它检查添加或减去一个月是否能安全地获得当天所需的月份。如果没有,那么它安全地做到了。

添加月份时,会增加15,以便安全地进入下个月,然后返回当月的最后一天。 减去月数时,它需要在本月的第一天减去1。

注意:正如所写,这适用于+1个月或-1个月


    function _my_strtotime($offset, $reference_date){

           //$offset is a string such as (+1 month)

       if(strpos($offset, 'month') === false){
         //exit if not addin/subtracing months
         return strtotime($offset, $reference_date);
       }

       $other_months_date = strtotime ( $offset, $reference_date );
       $day_of_other_month = date( 'd', $other_months_date );
       $day_of_reference_month = date('d', $reference_date );

       //check if numerical day is different. If so manipulate.
       if($day_of_reference_month != $day_of_other_month){
         if(strpos($offset, '-') === false){
           // adding months
           return strtotime('last day of this month', strtotime('+15 days', $reference_date));
         } else {
           // subtracing months
           return strtotime('-1 day', strtotime('first day of this month', $reference_date));
         }

       }

       return strtotime($offset, $reference_date);

     }

测试结果:


    input=2016-01-31  (+1 month)  output=2016-02-29 //leap year

    input=2017-01-31  (+1 month) output=2017-02-28

    input=2018-05-31 (+1 month) output=2018-06-30

    input=2018-07-31 (-1 month) output=2018-06-30

    input=2016-07-22 (-1 month) output=2016-06-22

    input=2016-07-22 (+1 month) output=2016-08-22

答案 15 :(得分:-1)

这是我使用的

这是当前月份日期的时间戳

$month_timestamp = strtotime(date('Y-m', $create_timestamp));

当天

$current_day = date('d');

这是下个月的同一天,格式为“Y-m-d”

$next_month_first = date('Y-m-' . $current_day, strtotime('next month', $month_timestamp));