В следующем месяце, в тот же день в PHP

У меня есть «событие», которое нужно планировать в тот же день каждого месяца.

Предположим, что вы установили дату начала 1 мая, вы должны получить следующие события 1 июня, 1 июля и т. Д. Проблема связана с датой начала 31-го (следующие могут быть 30 или 28 в зависимости от месяца) ,

Учитывая, что существуют месяцы с различным количеством дней (28, 30, 31) в зависимости от самого месяца и года … что было бы простым способом настроить это?

Рассмотрим следующую (и ошибочную) следующую следующую функцию:

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

Отредактировано для добавления: Проблема для меня – достаточно просто, как решить, какое количество дней в любом конкретном месяце и, следовательно, получить следующую соответствующую дату.

Обновить:

Это даст вам количество дней в данном месяце:

 echo date('t', $timestamp); 

См.: Date ()

Старый ответ:

Я не уверен в алгоритме, о котором вы думаете, но я считаю, что это поможет вам:

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

Это вернет правильную временную метку за 10 месяцев вперед: mktime(0,0,0,date("m")+$X,date('d'),date("Y"));

Попробуй это. reday – день для пополнения (int – день месяца). Если меньше, чем сегодня, это даст reday этого месяца, но не намного больше. дней этого месяца. Если больше, чем сегодня, давайте reday следующий месяц в том же состоянии. Я использую это для расчета «Next refill» ежемесячной точки заправки. return 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; } } } 

для более прямого указания (Edit)

 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; } } 

Я рекомендую прочитать следующий комментарий на php.net. strtotime () (php.net)

Изменить: Следующий ответ дает «резюме» ссылки, которую я опубликовал, для тех, кто не может расшифровать содержание, показанное там.

Поскольку месяцы настолько разнообразны по размеру, не лучший способ установить следующий месяц – это что-то вроде: в этот день, в следующем месяце, за исключением случаев, когда этот день не существует в следующем месяце.

Пример:

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

или просто, strtotime("+1 month")

Пробовал это как жаворонок, и он действительно работает

 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('md-Y', $last_day_next_month); } else { $date = date('md-Y', $today_next_month); } echo "And the winner is : $date<br/>"; 

просто

 public function adicionarMesMantendoDia($date, $months, $format = "Ymd"){ $date = \DateTime::createFromFormat($format, $date); for($i=0;$i < $months; $i++){ $date->modify('+ ' . date("t", $date->getTimestamp()) . ' day'); } return $date; } 

Как насчет этой функции:

  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; } 

На веб-сайте php.net имеется другое решение под заголовком strtotime в комментариях .

Никто не упоминает эту альтернативу, хотя результат такой же, как и другие, и, вероятно, не то, что ищет OP:

 $today = new DateTime(); $today->modify("+1 month"); echo $today->format("dmY"); 

Почему бы не просто сохранить месяц и день отдельно и увеличить месяц на единицу, а затем использовать функцию проверки PHP для проверки даты, уменьшая день за кадром до даты?

Я знаю, что это старый пост, но он думал о другом подходе.

Поэтому вместо того, чтобы пытаться выяснить дни в месяц (что несколько сложно), можно легко найти следующий месяц, используя текущий месяц, например:

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

Затем получите день текущего месяца, используя date("d") , и сравните с последующим месяцем из приведенного выше кода.

У меня также была такая же проблема, но когда я попробовал над решениями, они не могли работать отлично для меня, я попытался на своем конце и придумал новое решение, которое:

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

Datetime OOP Style

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

Это то, что я использую

Это отметка даты текущего месяца

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

Сегодня

 $current_day = date('d'); 

И это в следующем месяце в тот же день в формате «Ymd»

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

Ни одно из вышеперечисленных не заботилось о не существующих днях (например, 30 февраля или 31 апреля), так что вот моя функция:

 <?php function getSameDayNextMonth($time, $numberMonthsToAdd = 1) { list($year, $month, $day) = explode('-', date("Ymd", $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("Ymd", $_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 */