PHP Date diff with a difference -


please bear me try explain predicament. need somehow difference between 2 dates reversing function have add months , years?

problem date add function provided php >= 5.3 not add dates in manner require. example: +3 months 30nov = 2mar

solution use function below (code ref 2) produce results need. example: +3 months 30nov = 28feb

however when using below (code ref 1) calculate difference based on addition function provide php >= 5.3 in 2 instead of 3 months difference between 30nov , 28feb.

if come accurate date diff based on code ref 2 logic i, , i'm sure others in same boat grateful.

<< 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('y-m-d'); // 2001-02-28 ?> 

solution found

by changing way use original function instead find out number of years , months desired, many helpful suggestions. reason y=1 , m=4 because year starts @ 1 , month starts @ one, otherwise 0 , 3 requested if starting @ zero.

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

the way approach extend datetime , overide add() , sub() methods behave want them to. that, after 1 of advantages of oop.

the way desired behaviours set day of month 1st before doing calling add() or sub() , restoring original or highest possible day afterwards.

my first attempt below, not thoroughly tested, adding 1 month 31st jan gave 28th feb, which, believe desired behaviour:-

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

here working example using exampe dates

here example using diff() method can see gives 3 month difference. can see adding resulting dateinterval original date results in second date.

the sub() method may require bit more thought, don't have time now. i'll take more thorough if few spare minutes later.


Comments

Popular posts from this blog

ios - UICollectionView Self Sizing Cells with Auto Layout -

node.js - ldapjs - write after end error -

DOM Manipulation in Wordpress (and elsewhere) using php -