2 个类
DateTime
和 DateTimeImmutable
实现相同的接口 DateTimeInterface
。因此我想知道:
这两个类DateTime
和
DateTimeImmutable
有什么区别?
差异的核心在DateTime
类的
文档中描述:
该类的行为与 DateTimeImmutable 相同,只是当调用 DateTime::modify() 等修改方法时对象会被修改。
让我们通过一个具体的例子来观察这种差异:
$date = new DateTime();
$tomorrow = $date->modify('+1 day');
echo $date->format('Y-m-d');
echo $tomorrow->format('Y-m-d');
这将输出:
2021-05-15
2021-05-15
这里发生的事情是
modify
返回了 DateTime
对象的相同实例。变量 $tomorrow
不包含不同的对象,它包含对原始对象的引用。更新新变量也修改了原始变量。
如果我们执行相同的修改,但在不可变版本上:
$date = new DateTimeImmutable();
$tomorrow = $date->modify('+1 day');
echo $date->format('Y-m-d');
echo $tomorrow->format('Y-m-d');
这将输出:
2021-05-14
2021-05-15
因为在
DateTimeImmutable
中,修改方法不会返回相同的实例,它们会为您提供一个新的实例(也是不可变的)。这也意味着您必须将其结果分配给不可变版本的变量(如前面的示例所示)才能使用它:
$date = new DateTime('2021-05-14');
$date->modify('+1 day');
echo $date->format('Y-m-d'); // 2021-05-15
$date = new DateTimeImmutable('2021-05-14');
$date->modify('+1 day');
echo $date->format('Y-m-d'); // 2021-05-14; original is untouched
由于这种行为,不可变版本几乎总是优于可变版本。意外修改您无意修改的日期实例是一种很常见的错误。
您可能更喜欢可变版本,以避免在您可以可靠地确定不存在损害应用程序状态的危险的情况下进行赋值步骤,但是一旦您牢牢掌握了概念,最好还是进行估计。
除了
modify
之外,以下方法也被视为变异:
add
sub
setDate
setISODate
setTime
setTimezone
区别在于“不可变”部分,这意味着一旦创建对象,它就永远不会改变(wiki 了解更多信息)。这意味着每当您修改
DateTime
时,同一个实例都会被更改,但是当您修改 DateTimeImmutable
时,将返回一个新的修改后的实例。
一般来说,不可变对象在创建后永远不会改变其状态。相反,当需要修改时,它将返回具有修改状态的同一类的新实例。
它们都实现相同的 DateTimeInterface 的事实有点令人困惑,但可以通过以下事实来解释:该接口没有描述 DateTime 和 DateTimeImmutable 提供的所有可用功能。更准确地说,该接口不涵盖允许状态更改的方法。
选择其中之一的用例主要取决于偏好、编码标准,以及在某种程度上,对代码质量的需求与对开发速度的需求。
简单说明一下: 如果你想避免赋值过程,你可以连接:
echo $date->modify('+1 day')->format('Y-m-d');
假设 $date
是 DateTimeImmutable
对象。
示例:
$date = new DateTimeImmutable('2022-05-01');
$days = rand(2, 10);
echo "Date is: " . $date->format('d/m/Y')."\r\n";
echo "Now adding " .$days." days\r\n";
echo "Date now is: " . $date->modify('+'.$days.' day')->format('d/m/Y');
一个小脚本来查看差异: