PHP Date diff с разницей

Пожалуйста, несите меня, когда я пытаюсь объяснить свое затруднительное положение. Мне нужно как-то получить разницу между двумя датами, изменив функцию, которую я должен добавить месяцами и годами?

Проблема Функция добавления даты, предоставляемая с помощью PHP> = 5.3, не добавляет даты в соответствии с требованиями. Пример: от 3 месяцев до 30Nov = 2Mar

Решение. Я использую функцию ниже (код 2) для получения нужных мне результатов. Пример: от 3 месяцев до 30Nov = 28Feb

Однако при использовании ниже (код ref 1), чтобы вычислить разницу, которую он делает на основе функции добавления, укажите PHP> = 5.3, в которой я получаю 2 вместо 3-месячной разницы между 30Nov и 28Feb.

Если кто-то может помочь придумать точную дату, основанную на логике кода 2, я уверен, что другие в одной лодке будут очень благодарны.

<< CODE REF 1 >>

<?php $datetime1 = new DateTime('2000-11-30'); $datetime2 = new DateTime('2001-02-28'); $interval = $datetime1->diff($datetime2); echo $interval->format('%m'); // 2 $datetime1 = new DateTime('2000-11-30'); $datetime2 = new DateTime('2001-03-02'); $interval = $datetime1->diff($datetime2); echo $interval->format('%m'); // 3 ?> 

<< CODE REF 2 >>

 <?php $datetime = new DateTime('2000-11-30'); $y = 0; $m = 3; $d = 0; if ($d>0){ $datetime->add(new DateInterval('P'.$d.'D')); } if ($d<0){ $datetime->sub(new DateInterval('P'.$d.'D')); } if ($y!=0){ $init=clone $datetime; $modifier=$y.' years'; $datetime->modify($modifier); while ($datetime->format('m')!=$init->format('m')){ $datetime->modify('-1 day'); } } if ($m!=0){ $init=clone $datetime; $modifier=$m.' months'; $back_modifier =-$m.' months'; $datetime->modify($modifier); $back_to_init= clone $datetime; $back_to_init->modify($back_modifier); while ($init->format('m')!=$back_to_init->format('m')){ $datetime->modify('-1 day'); $back_to_init= clone $datetime; $back_to_init->modify($back_modifier); } } echo $datetime->format('Ym-d'); // 2001-02-28 ?> 

РЕШЕНИЕ НАЙДЕНО

Изменяя способ использования оригинальной функции, мы вместо этого выясняем количество лет и месяцев по желанию, большое спасибо всем полезным предложениям. Причина для y = 1 и m = 4 состоит в том, что год начинается с одного и месяца начинается с одного, иначе это будет 0 и 3, как первоначально запрашивалось, если начинать с нуля.

 <?php function date_yr_mth($date1='2000-11-30',$date2='2001-02-28'){ $y1 = date("Y", strtotime($date1)); $m1 = date("n", strtotime($date1)); $d1 = date("j", strtotime($date1)); $y2 = date("Y", strtotime($date2)); $m2 = date("n", strtotime($date2)); $d2 = date("j", strtotime($date2)); $t2 = date("t", strtotime($date2)); $cm_diff = $m2-$m1; $cy_diff = $y2-$y1; if ($d2>=$d1){ $add_mth1 = 1; }else{ $add_mth1 = 0; } $add_mth2 = 12*$cy_diff+$cm_diff; if ($d2==$t2 && $d2<$d1){ $add_mth3 = 1; }else{ $add_mth3 = 0; } $total_mths = $add_mth1+$add_mth2+$add_mth3; $arr = array(); $arr['y'] = floor(($total_mths-1)/12)+1; $arr['m'] = $total_mths-($arr['y']-1)*12; print_r($arr); // [y] => 1 // [m] => 4 } ?> 

Способ приблизиться к этому – расширить DateTime и переопределить методы add () и sub (), чтобы вести себя так, как вы хотите. Это, в конце концов, одно из преимуществ ООП.

Способ получить желаемое поведение – установить день месяца на 1-й, прежде чем делать вызов add () или sub (), а затем восстанавливать исходный или самый высокий возможный день после этого.

Моя первая попытка ниже, но не полностью протестирована, но добавление от 1 месяца до 31 января датировано 28 февраля, что, я считаю, является вашим желаемым поведением:

 class MyDateTime extends \DateTime { public function add($interval) { $oldDay = (int)$this->format('d'); $this->setDate((int)$this->format('Y'), (int)$this->format('m'), 1); parent::add($interval); $maxDay = (int)$this->format('t'); if($oldDay > $maxDay){ $this->setDate((int)$this->format('Y'), (int)$this->format('m'), $maxDay); } else { $this->setDate((int)$this->format('Y'), (int)$this->format('m'), $oldDay); } return $this; } public function sub($interval) { $oldDay = (int)$this->format('d'); $this->setDate((int)$this->format('Y'), (int)$this->format('m'), 1); parent::sub($interval); $maxDay = (int)$this->format('t'); if($oldDay > $maxDay){ $this->setDate((int)$this->format('Y'), (int)$this->format('m'), $maxDay); } else { $this->setDate((int)$this->format('Y'), (int)$this->format('m'), $oldDay); } return $this; } public function diff($dateTime2, $absolute = false) { if((int)$this->format('t') > (int)$dateTime2->format('t')){ $this->setDate((int)$this->format('Y'), (int)$this->format('m'), (int)$dateTime2->format('t')); } if((int)$this->format('t') < (int)$dateTime2->format('t')){ $dateTime2->setDate((int)$dateTime2->format('Y'), (int)$dateTime2->format('m'), (int)$this->format('t')); } return parent::diff($dateTime2, $absolute); } } к class MyDateTime extends \DateTime { public function add($interval) { $oldDay = (int)$this->format('d'); $this->setDate((int)$this->format('Y'), (int)$this->format('m'), 1); parent::add($interval); $maxDay = (int)$this->format('t'); if($oldDay > $maxDay){ $this->setDate((int)$this->format('Y'), (int)$this->format('m'), $maxDay); } else { $this->setDate((int)$this->format('Y'), (int)$this->format('m'), $oldDay); } return $this; } public function sub($interval) { $oldDay = (int)$this->format('d'); $this->setDate((int)$this->format('Y'), (int)$this->format('m'), 1); parent::sub($interval); $maxDay = (int)$this->format('t'); if($oldDay > $maxDay){ $this->setDate((int)$this->format('Y'), (int)$this->format('m'), $maxDay); } else { $this->setDate((int)$this->format('Y'), (int)$this->format('m'), $oldDay); } return $this; } public function diff($dateTime2, $absolute = false) { if((int)$this->format('t') > (int)$dateTime2->format('t')){ $this->setDate((int)$this->format('Y'), (int)$this->format('m'), (int)$dateTime2->format('t')); } if((int)$this->format('t') < (int)$dateTime2->format('t')){ $dateTime2->setDate((int)$dateTime2->format('Y'), (int)$dateTime2->format('m'), (int)$this->format('t')); } return parent::diff($dateTime2, $absolute); } } 

Вот пример работы с датами экзамена

Вот пример использования метода diff (), поскольку вы видите, что он дает разницу в 3 месяца. Вы также можете видеть, что добавление итогового DateInterval к ​​исходной дате приводит к второй дате.

Метод sub () может потребовать немного больше мысли, но у меня нет времени только сейчас. Я посмотрю более внимательно, если через несколько минут я получу несколько запасных минут.

Таким образом, вы получите абсолютную разницу между месяцами, не принимая во внимание день.

  <?php function getMonthDiff($firstMonth, $secondMonth) { $firstMonth = $firstMonth->format("Y") * 12 + $firstMonth->format("m"); $secondMonth = $secondMonth->format("Y") * 12 + $secondMonth->format("m"); return abs($firstMonth - $secondMonth); } $datetime1 = new DateTime('2000-11-30'); $datetime2 = new DateTime('2001-02-28'); echo getMonthDiff($datetime1, $datetime2); echo "<br />"; $datetime1 = new DateTime('2000-11-30'); $datetime2 = new DateTime('2001-03-02'); echo getMonthDiff($datetime1, $datetime2);