PHP日期差异与差异

时间:2013-08-13 08:18:01

标签: php date datediff

当我试图解释我的困境时,请耐心等待。我需要以某种方式通过反转我必须添加几个月和几年的函数来获得两个日期之间的差异?

问题 PHP> = 5.3提供的日期添加功能不会以我需要的方式添加日期。 示例:+3个月到30Nov = 2Mar

解决方案 我使用下面的函数(代码ref 2)来产生我需要的结果。 示例:+3个月到30Nov = 28Feb

然而,当使用下面的代码(代码ref 1)计算差异时,它会根据添加函数提供PHP> = 5.3,因为我在30Nov和28Feb之间得到2而不是3个月的差异。

如果有人可以根据代码参考2逻辑I提出准确的日期差异,我相信同一条船上的其他人会非常感激。

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

&LT;&LT; CODE REF 2&gt;&gt;

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

解决方案

通过改变我们使用原始功能的方式,我们可以根据需要找出年数和月数,非常感谢所有有用的建议。 y = 1和m = 4的原因是因为年份从1开始,月份从1开始,否则如果从零开始,它将是最初请求的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
}
?>

2 个答案:

答案 0 :(得分:2)

解决这个问题的方法是扩展DateTime并覆盖add()和sub()方法,使其按照您的意愿运行。毕竟这是OOP的优势之一。

获得所需行为的方法是在调用add()或sub()之前将月中的日期设置为1,然后在之后恢复原始日期或最高日期。

我的第一次尝试是在下面,没有经过彻底的测试,但是1月31日的1个月到2月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);
    }
}

Here is a working example using your exampe dates

Here is an example using the diff() method你可以看到它给出了3个月的差异。您还可以看到将生成的DateInterval添加到原始日期会导致第二个日期。

sub()方法可能需要更多考虑,但我现在没有时间。如果我在几分钟之后得到几分钟,我会更加透彻。

答案 1 :(得分:1)

通过这种方式,您可以在不考虑当天的情况下获得月份之间的绝对差异。

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