两个 Carbon 变量用 `>` 比较大小

两个 Carbon 变量比较大小,直接用 > 号比较会有什么问题吗?:
我测试没有发现问题
那么> 比较和 $startTime->gt($endTime)有什么区别呢?

if ($startTime > $endTime) {
    throw new Exception ();
}
我未曾珍惜的,我不再拥有?‍?️
附言 1  ·  2年前

找到了 官方文档

Those methods use natural comparisons offered by PHP $date1 == $date2 so all of them will ignore milli/micro-seconds before PHP 7.1, then take them into account starting with 7.1.

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
leo
最佳答案

Datetime 类型的对象是可以用 > < 直接比较的,Carbon 继承了 Datetime 所以也是没问题的,官方文档

file

2年前 评论
leo (作者) 2年前
wanghan 2年前
忆往昔弹指间 2年前
讨论数量: 10

按照我的理解是没有问题的,这里在比较的时候会转成string

2年前 评论
haodudecao (楼主) 2年前
勇敢的心 (作者) 2年前

有风险


// carbon 的 toString 实现,转换成字符串会用到这些,如果日期,时间 是2位有效的,比较没有问题,如果是1位的就可能出现不可预知的问题
    public function __toString()
    {
        $format = $this->localToStringFormat ?? static::$toStringFormat;

        return $format instanceof Closure
            ? $format($this)
            : $this->rawFormat($format ?: (
                \defined('static::DEFAULT_TO_STRING_FORMAT')
                    ? static::DEFAULT_TO_STRING_FORMAT
                    : CarbonInterface::DEFAULT_TO_STRING_FORMAT
            ));
    }
//  $this->localToStringFormat 这个有被修改的可能
// Carbon\Traits\Options; // trait
public function settings(array $settings)
{
    $this->localToStringFormat = $settings['toStringFormat'] ?? null;
}

建议使用时间戳 Carbon::now()->getTimestamp() 进行比较

2年前 评论

这是非常不严谨的行为,不建议这么比较,也许本次得到的正确结果只是一个巧合,它会产生很多意外情况,可以参考如下示例代码:

<?php

class Time
{
    public $default;
    public $timestamp;

    public function setDefault($val)
    {
        $this->default = $val;
    }

    public function setTimestamp($val)
    {
        $this->timestamp = $val;
    }

    public function __toString()
    {
        var_dump('__toString');
        return (string)$this->timestamp;
    }
}

$startTime = new Time();
$endTime = new Time();
$time = time();

$startTime->setTimestamp($time + 100);
$endTime->setTimestamp($time);
var_dump($startTime > $endTime);
echo '--------------------' . PHP_EOL;

$startTime->setDefault(1);
$endTime->setDefault(10000000000);
var_dump($startTime > $endTime);
echo '--------------------' . PHP_EOL;

var_dump(strval($startTime) > strval($endTime));
echo '--------------------' . PHP_EOL;

echo $startTime;


// 所有输出
bool(true)
--------------------
bool(false)
--------------------
string(10) "__toString"
string(10) "__toString"
bool(true)
--------------------
string(10) "__toString"
1650770995

观察代码输出可知几个结论:

  1. 当我们用对象进行大小比较时,__toString()并没有如期运行,只有明确作为字符串输出时,__toString()才工作。
  2. 我们发现,比较对象时,它可能是比较的所有对象属性(仅仅只是猜测的可能,也许是个错误结论),第一次打印的结果是符合预期的。第二次,因为 $default 的值得干扰,这时候的结果,并不符合预期。第三次打印明确指定了字符串,__toString()工作了,这时候结果是正确的。
2年前 评论

输出时间戳来比较吧

2年前 评论
leo

Datetime 类型的对象是可以用 > < 直接比较的,Carbon 继承了 Datetime 所以也是没问题的,官方文档

file

2年前 评论
leo (作者) 2年前
wanghan 2年前
忆往昔弹指间 2年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!