DateTimeImmutable 与 DateTime

DateTimeImmutable vs DateTime

2类DateTimeDateTimeImmutable实现了相同的接口DateTimeInterface。所以我想知道:

这2个类DateTimeDateTimeImmutable有什么区别

区别在于 'immutable' 部分,这意味着对象一旦创建就永远无法更改 (wiki for more info)。这意味着每当您修改 DateTime 时,相同的实例将被更改,但是当您修改 DateTimeImmutable 时,新修改的实例将是 return。

一般来说,不可变对象在创建后永远不会改变它的状态。相反,当需要修改时,它将 return 具有修改后状态的相同 class 的新实例。

事实上,它们都实现了相同的 DateTimeInterface is a bit confusing, but can be explained by the fact that the interface does not describe all available functions that the DateTime and DateTimeImmutable 提议。更准确地说,该接口不包括允许状态更改的方法。

选择一个或另一个的用例主要取决于偏好、编码标准,并且在某种程度上,需要代码质量与需要开发速度。

核心区别在documentation中描述DateTimeclass:

This class behaves the same as DateTimeImmutable except objects are modified itself when modification methods such as DateTime::modify() are called.

让我们通过一个具体的例子来观察这种差异:

$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 returned 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中,修改方法不是return同一个实例,它们给你一个新的(也是不可变的)。这也意味着您必须将其结果分配给不可变版本的变量(如上例所示)才能使用它:

$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

简单说明一下: 如果你想避免分配过程,你可以连接:echo $date->modify('+1 day')->format('Y-m-d'); 假设 $dateDateTimeImmutable 对象。

示例:

$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');