我们如何在 PHP 中添加两个日期间隔

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11556731/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 00:46:12  来源:igfitidea点击:

How we can add two date intervals in PHP

phpdatetimeadditiondateinterval

提问by Sheikh Rahat Ali

i want to add two date intervals to calculate the total duration in hours and minutes in fact i want to perform addittion as shown below:

我想添加两个日期间隔来计算以小时和分钟为单位的总持续时间实际上我想执行如下所示的加法:

$a = new DateTime('14:25');
$b = new DateTime('17:30');
$interval1 = $a->diff($b);
echo "interval 1 : " . $interval1->format("%H:%I");
echo "<br />";

$c = new DateTime('08:00');
$d = new DateTime('13:00');
$interval2 = $c->diff($d);
echo "interval 2 : " . $interval2->format("%H:%I");
echo "<br />";

echo "Total interval : " . $interval1 + $interval2;

Any idea how to perform this type of interval addition to get the sum of the two intervals in total hours and minutes format in PHP

知道如何执行这种类型的间隔加法以在 PHP 中以总小时和分钟格式获得两个间隔的总和

回答by hakre

PHP has no operator overloading* so +with objects makes PHP trying it to convert them to string first, but DateIntervaldoes not support that:

PHP 没有运算符重载*,因此+使用对象会使 PHP 首先尝试将它们转换为字符串,但DateInterval不支持:

interval 1: 03:05
interval 2: 05:00
Total interval : 08:05

Instead you need to create a new DateTimeobject, then use the addfunction to add the intervals and finally display the difference to the reference point:

相反,您需要创建一个新DateTime对象,然后使用该add函数添加间隔,最后显示与参考点的差异:

$e = new DateTime('00:00');
$f = clone $e;
$e->add($interval1);
$e->add($interval2);
echo "Total interval : ", $f->diff($e)->format("%H:%I"), "\n";

Full Exmaple/(Demo):

完整示例/(演示):

$a = new DateTime('14:25');
$b = new DateTime('17:30');
$interval1 = $a->diff($b);
echo "interval 1: ", $interval1->format("%H:%I"), "\n";

$c = new DateTime('08:00');
$d = new DateTime('13:00');
$interval2 = $c->diff($d);
echo "interval 2: ", $interval2->format("%H:%I"), "\n";

$e = new DateTime('00:00');
$f = clone $e;
$e->add($interval1);
$e->add($interval2);
echo "Total interval : ", $f->diff($e)->format("%H:%I"), "\n";


You might also want to consider looking how DateIntervalstores its' values and then extend from it to do the calculation your own. The following example (Demo) is rough, it does not take into account the inverted thingy, it does not (re)set $daysto falseand I have not checked/tested the ISO specification of the period specifier on creationbut I think it is enough to show the idea:

您可能还需要考虑查看如何DateInterval存储其值,然后从中扩展以进行您自己的计算。下面的例子(Demo)很粗略,它没有考虑到倒置的东西,它没有(重新)设置$daysfalse并且我没有检查/测试创建时周期说明符的 ISO 规范,但我认为它足以展示这个想法:

class MyDateInterval extends DateInterval
{
    /**
     * @return MyDateInterval
     */
    public static function fromDateInterval(DateInterval $from)
    {
        return new MyDateInterval($from->format('P%yY%dDT%hH%iM%sS'));
    }

    public function add(DateInterval $interval)
    {
        foreach (str_split('ymdhis') as $prop)
        {
            $this->$prop += $interval->$prop;
        }
    }
}

$a = new DateTime('14:25');
$b = new DateTime('17:30');
$interval1 = $a->diff($b);
echo "interval 1: ", $interval1->format("%H:%I"), "\n";

$c = new DateTime('08:00');
$d = new DateTime('13:00');
$interval2 = $c->diff($d);
echo "interval 2: ", $interval2->format("%H:%I"), "\n";

$e = MyDateInterval::fromDateInterval($interval1);
$e->add($interval2);
echo "Total interval: ", $e->format("%H:%I"), "\n";


*If you write a PHP extension, it actually is possible (at least sort-of).

*如果你写一个 PHP 扩展,它实际上是可能的(至少有点)。

回答by dave1010

This function allows you to combine any number of DateIntervals

此函数允许您组合任意数量的 DateIntervals

/**
 * Combine a number of DateIntervals into 1 
 * @param DateInterval $...
 * @return DateInterval
 */
function addDateIntervals()
{
    $reference = new DateTimeImmutable;
    $endTime = clone $reference;

    foreach (func_get_args() as $dateInterval) {
        $endTime = $endTime->add($dateInterval);
    }

    return $reference->diff($endTime);
}

回答by Carlos Arturo Alaniz

function compare_dateInterval($interval1, $operator ,$interval2){
    $interval1_str = $interval1->format("%Y%M%D%H%I%S");
    $interval2_str = $interval2->format("%Y%M%D%H%I%S");
    switch($operator){
        case "<":
            return $interval1 < $interval2;
        case ">":
            return $interval1 > $interval2;
        case "==" :
            return $interval1 == $interval2;
        default:
            return NULL;
    }
}
function add_dateInterval($interval1, $interval2){
    //variables
    $new_value= [];
    $carry_val = array(
                    's'=>['value'=>60,'carry_to'=>'i'],
                    'i'=>['value'=>60,'carry_to'=>'h'],
                    'h'=>['value'=>24,'carry_to'=>'d'],
                    'm'=>['value'=>12,'carry_to'=>'y']
                );

    //operator selection
    $operator = ($interval1->invert == $interval2->invert) ? '+' : '-';

    //Set Invert
    if($operator == '-'){
        $new_value['invert'] = compare_dateInterval($interval1,">",$interval2)?$interval1->invert:$interval2->invert;
    }else{
        $new_value['invert'] = $interval1->invert;
    }

    //Evaluate
    foreach( str_split("ymdhis") as $property){
        $expression = 'return '.$interval1->$property.' '.$operator.' '.$interval2->$property.';';
        $new_value[$property] = eval($expression);
        $new_value[$property] = ($new_value[$property] > 0) ? $new_value[$property] : -$new_value[$property];
        }

    //carry up
    foreach($carry_val as $property => $option){
        if($new_value[$property] >= $option['value']){
            //Modulus
            $new_value[$property] = $new_value[$property] % $option['value'];
            //carry over
            $new_value[$option['carry_to']]++;
        }
    }

    $nv = $new_value;
    $result = new DateInterval("P$nv[y]Y$nv[m]M$nv[d]DT$nv[h]H$nv[i]M$nv[s]S");
    $result->invert = $new_value['invert'];
    return $result;
}

$a = new DateTime('00:0');
$b = new DateTime('17:30');
$interval1 = $a->diff($b);
echo "interval 1: ", $interval1->format("%H:%I"), "<br>";

$c = new DateTime('08:01:00');
$d = new DateTime('13:30:33');
$interval2 = $c->diff($d);
echo "interval 2: ", $interval2->format("%H:%I"), "<br>";

$addition = add_dateInterval($interval1,$interval2);
echo "<pre>";
echo var_dump($addition);
echo "</pre>";