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

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

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

找到了 官方文档

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.

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
leo
最佳答案

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

file

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

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

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

有风险


// 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() 进行比较

1年前 评论

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

<?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()工作了,这时候结果是正确的。
1年前 评论

输出时间戳来比较吧

1年前 评论
leo

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

file

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

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