Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP日期间隔是否与DateTime类似?_Php_Datetime_Dateinterval - Fatal编程技术网

PHP日期间隔是否与DateTime类似?

PHP日期间隔是否与DateTime类似?,php,datetime,dateinterval,Php,Datetime,Dateinterval,我发现PHP中的DateTime对象可以与另一个对象进行比较,如“>”和“”$aujourdhui从何而来?当然在语言上它与$today相同,但PHP不知道!将代码更改为使用$today将打印“oK” 如果未定义,$aujourdhui->diff($release)将计算为0,前提是您的PHP解释器没有因错误而中止(我的解释器是如此)。看起来有一个,不确定它是否在主干中。这两种方式都没有文档记录(我可以找到),因此使用可能不安全 也就是说,在一些测试之后,似乎可以对它们进行比较,但只有在以某种

我发现PHP中的DateTime对象可以与另一个对象进行比较,如“>”和“”
$aujourdhui
从何而来?当然在语言上它与
$today
相同,但PHP不知道!将代码更改为使用
$today
将打印
“oK”

如果未定义,
$aujourdhui->diff($release)
将计算为
0
,前提是您的PHP解释器没有因错误而中止(我的解释器是如此)。

看起来有一个,不确定它是否在主干中。这两种方式都没有文档记录(我可以找到),因此使用可能不安全

也就是说,在一些测试之后,似乎可以对它们进行比较,但只有在以某种方式对它们进行“评估”之后(进行var转储会改变结果)。以下是我的测试/结果:

<?php
$int15 = new DateInterval('P15D');
$int20 = new DateInterval('P20D');

var_dump($int15 > $int20); //should be false;
var_dump($int20 > $int15); //should be true;

var_dump($int15 < $int20); //should be true;
var_dump($int20 < $int15); //should be false;

var_dump($int15);
var_dump($int20);

var_dump($int15 > $int20); //should be false;
var_dump($int20 > $int15); //should be true;

var_dump($int15 < $int20); //should be true;
var_dump($int20 < $int15); //should be false;

$date = new DateTime();
$diff = $date->diff(new DateTime("+10 days"));

var_dump($int15 < $diff); //should be false;
var_dump($diff < $int15); //should be true;

var_dump($int15 > $diff); //should be true;
var_dump($diff > $int15); //should be false;

var_dump($diff);

var_dump($int15 < $diff); //should be false;
var_dump($diff < $int15); //should be true;

var_dump($int15 > $diff); //should be true;
var_dump($diff > $int15); //should be false;

我使用了以下方法来比较日期间隔:

version_compare(join('.', (array) $dateIntervalA), join('.', (array) $dateIntervalB));
编辑:

class ComparableDateInterval extends DateInterval
{
    /** 
     * Leap-year safe comparison of DateInterval objects.
     */
    public function compare(DateInterval $oDateInterval)
    {   
        $fakeStartDate1 = date_create();
        $fakeStartDate2 = clone $fakeStartDate1;
        $fakeEndDate1   = $fakeStartDate1->add($this);
        $fakeEndDate2   = $fakeStartDate2->add($oDateInterval);

        if($fakeEndDate1 < $fakeEndDate2) {
            return -1; 
        } elseif($fakeEndDate1 == $fakeEndDate2) {
            return 0;
        }   
        return 1;
    }   
}

$int15 = new ComparableDateInterval('P15D');
$int20 = new ComparableDateInterval('P20D');

var_dump($int15->compare($int20) == -1); // should be true;
这是密码

/**
 * The stock DateInterval never got the patch to compare.
 * Let's reimplement the patch in userspace.
 * See the original patch at http://www.adamharvey.name/patches/DateInterval-comparators.patch
 */
class ComparableDateInterval extends DateInterval
{
    static public function create(DateInterval $oDateInterval)
    {
        $oDi         = new ComparableDateInterval('P1D');
        $oDi->s      = $oDateInterval->s;
        $oDi->i      = $oDateInterval->i;
        $oDi->h      = $oDateInterval->h;
        $oDi->days   = $oDateInterval->days;
        $oDi->d      = $oDateInterval->d;
        $oDi->m      = $oDateInterval->m;
        $oDi->y      = $oDateInterval->y;
        $oDi->invert = $oDateInterval->invert;

        return $oDi;
    }

    public function compare(DateInterval $oDateInterval)
    {
        $oMyTotalSeconds   = $this->getTotalSeconds();
        $oYourTotalSeconds = $oDateInterval->getTotalSeconds();

        if($oMyTotalSeconds < $oYourTotalSeconds)
            return -1;
        elseif($oMyTotalSeconds == $oYourTotalSeconds)
            return 0;
        return 1;
    }

    /**
     * If $this->days has been calculated, we know it's accurate, so we'll use
     * that. If not, we need to make an assumption about month and year length,
     * which isn't necessarily a good idea. I've defined months as 30 days and
     * years as 365 days completely out of thin air, since I don't have the ISO
     * 8601 spec available to check if there's a standard assumption, but we
     * may in fact want to error out if we don't have $this->days available.
     */
    public function getTotalSeconds()
    {
        $iSeconds = $this->s + ($this->i * 60) + ($this->h * 3600);

        if($this->days > 0)
            $iSeconds += ($this->days * 86400);

        // @note Maybe you prefer to throw an Exception here per the note above
        else
            $iSeconds += ($this->d * 86400) + ($this->m * 2592000) + ($this->y * 31536000);

        if($this->invert)
            $iSeconds *= -1;

        return $iSeconds;
    }
}
/**
*stock DateInterval从未获得要比较的修补程序。
*让我们在用户空间中重新实现补丁。
*请参阅位于的原始修补程序http://www.adamharvey.name/patches/DateInterval-comparators.patch
*/
类CompariableDateInterval扩展了DateInterval
{
静态公共函数创建(DateInterval$oDateInterval)
{
$oDi=新的可比日期间隔(“P1D”);
$oDi->s=$oDateInterval->s;
$oDi->i=$oDateInterval->i;
$oDi->h=$oDateInterval->h;
$oDi->days=$oDateInterval->days;
$oDi->d=$oDateInterval->d;
$oDi->m=$oDateInterval->m;
$oDi->y=$oDateInterval->y;
$oDi->invert=$oDateInterval->invert;
返回$oDi;
}
公共函数比较(日期间隔$oDateInterval)
{
$myTotalSeconds=$this->getTotalSeconds();
$OyorTotalSeconds=$oDateInterval->getTotalSeconds();
如果($myTotalSeconds<$oYourTotalSeconds)
返回-1;
elseif($myTotalSeconds==$oYourTotalSeconds)
返回0;
返回1;
}
/**
*如果计算了$this->days,我们知道它是准确的,所以我们将使用
*如果不是的话,我们需要假设一个月和一年的长度,
*这不一定是个好主意。我把月定义为30天和30天
*由于我没有ISO认证,365天的时间完全是凭空而来的
*8601规范可用于检查是否存在标准假设,但我们
*事实上,如果我们没有$this->days可用,可能会想出错。
*/
公共函数getTotalSeconds()
{
$iSeconds=$this->s+($this->i*60)+($this->h*3600);
如果($this->days>0)
$iSeconds+=($this->days*86400);
//@note可能您更喜欢根据上面的注释在此处抛出异常
其他的
$iSeconds+=($this->d*86400)+($this->m*2592000)+($this->y*31536000);
如果($this->invert)
$iSeconds*=-1;
返回$iSeconds;
}
}

简而言之,当前默认情况下不支持比较
DateInterval
对象(从php 5.6开始)

如您所知,
DateTime
对象是可比较的

实现所需结果的一种方法是从
DateTime
对象中减去或添加
DateInterval
,然后比较两者以确定差异

例如:

$buildDate=新日期时间('2012-02-15');
$releaseDate=克隆$buildDate;
$releaseDate->setDate(2012,2,14);
$buildDate->add(新的日期间隔('P15D'));
var_dump($releaseDate<$buildDate);//bool(true)

编辑

在PHP7.1发布时,由于s

例如:

$a=new\DateTime;
$b=新建\日期时间;
var_dump($a<$b);
结果(7.1+):

结果(5.x-7.0.x,7.1.3):

为了避免这种行为,建议您使用
clone
来比较
DateTime
对象

例如:


不,现在不可能,将来也不可能。比较两个
DateInterval
有一个根本问题

DateInterval
是相对的,而
DateTime
是绝对的:
P1D
意味着一天,所以你会认为这意味着(24*60*60)86.400秒。但由于时间的限制,情况并非总是如此

这看起来是一种罕见的情况,别忘了将月与日进行比较更加困难:

P1M和P30D-哪一个更大?即使我是 现在在二月?或者是P30D即使我现在在 八月?PT24H3M和P1D怎么样?


如果您使用的时间间隔不超过一个月,则很容易将2个时间间隔转换为秒并进行比较。
$dateInterval->format(“%s”)
仅返回秒组件,因此我最终执行了以下操作:

function intervalToSeconds($dateInterval) {
        $s = (
            ($dateInterval->format("%d")*24*60*60) + 
            ($dateInterval->format("%h")*60*60) + 
            ($dateInterval->format("%i")*60) + 
            $dateInterval->format("%s")
        );
        return $s;
    }

抱歉,这只是一个失败的翻译。因为这只是个人测试,我没有用英语写。我编辑了我的帖子,问题仍然存在。这很奇怪……你使用的是什么版本的PHP?我在我的机器上用5.3.6版试过,它回显了
oK
!是的。我也不会。但现在我明白了发生了什么,这就是问题所在nt。我将使用sub/add和DateTime比较。它们更可靠。请参阅我的新答案,它可靠且易于使用。@quickshiftin正如artragis的评论所示,问题是关于实际行为,以及为什么它很奇怪。这回答了这个问题。不起作用:$int20=新的DATETERVAL('P20D');$int20_2=新的DATETERVAL('P20D'));var_dump(join(‘.,(array)$int20),join(‘.,(array)$int20_2));给出两个“等价版本”,但版本_comparesend(-1),因此不处理相等性。此外,我记得,当使用减法时,会在日期间隔内创建一个新字段,使之无法与手进行比较-
class ComparableDateInterval extends DateInterval
{
    /** 
     * Leap-year safe comparison of DateInterval objects.
     */
    public function compare(DateInterval $oDateInterval)
    {   
        $fakeStartDate1 = date_create();
        $fakeStartDate2 = clone $fakeStartDate1;
        $fakeEndDate1   = $fakeStartDate1->add($this);
        $fakeEndDate2   = $fakeStartDate2->add($oDateInterval);

        if($fakeEndDate1 < $fakeEndDate2) {
            return -1; 
        } elseif($fakeEndDate1 == $fakeEndDate2) {
            return 0;
        }   
        return 1;
    }   
}

$int15 = new ComparableDateInterval('P15D');
$int20 = new ComparableDateInterval('P20D');

var_dump($int15->compare($int20) == -1); // should be true;
$int15 = new ComparableDateInterval('P15D');
$int20 = new ComparableDateInterval('P20D');

var_dump($int15->compare($int20) == -1); // should be true;
/**
 * The stock DateInterval never got the patch to compare.
 * Let's reimplement the patch in userspace.
 * See the original patch at http://www.adamharvey.name/patches/DateInterval-comparators.patch
 */
class ComparableDateInterval extends DateInterval
{
    static public function create(DateInterval $oDateInterval)
    {
        $oDi         = new ComparableDateInterval('P1D');
        $oDi->s      = $oDateInterval->s;
        $oDi->i      = $oDateInterval->i;
        $oDi->h      = $oDateInterval->h;
        $oDi->days   = $oDateInterval->days;
        $oDi->d      = $oDateInterval->d;
        $oDi->m      = $oDateInterval->m;
        $oDi->y      = $oDateInterval->y;
        $oDi->invert = $oDateInterval->invert;

        return $oDi;
    }

    public function compare(DateInterval $oDateInterval)
    {
        $oMyTotalSeconds   = $this->getTotalSeconds();
        $oYourTotalSeconds = $oDateInterval->getTotalSeconds();

        if($oMyTotalSeconds < $oYourTotalSeconds)
            return -1;
        elseif($oMyTotalSeconds == $oYourTotalSeconds)
            return 0;
        return 1;
    }

    /**
     * If $this->days has been calculated, we know it's accurate, so we'll use
     * that. If not, we need to make an assumption about month and year length,
     * which isn't necessarily a good idea. I've defined months as 30 days and
     * years as 365 days completely out of thin air, since I don't have the ISO
     * 8601 spec available to check if there's a standard assumption, but we
     * may in fact want to error out if we don't have $this->days available.
     */
    public function getTotalSeconds()
    {
        $iSeconds = $this->s + ($this->i * 60) + ($this->h * 3600);

        if($this->days > 0)
            $iSeconds += ($this->days * 86400);

        // @note Maybe you prefer to throw an Exception here per the note above
        else
            $iSeconds += ($this->d * 86400) + ($this->m * 2592000) + ($this->y * 31536000);

        if($this->invert)
            $iSeconds *= -1;

        return $iSeconds;
    }
}
bool(true)
bool(false)
$a = new \DateTime;
$b = clone $a;
var_dump($a < $b);
bool(false)
function intervalToSeconds($dateInterval) {
        $s = (
            ($dateInterval->format("%d")*24*60*60) + 
            ($dateInterval->format("%h")*60*60) + 
            ($dateInterval->format("%i")*60) + 
            $dateInterval->format("%s")
        );
        return $s;
    }