DateInterval 不添加日期并且没有错误?

DateInterval doesnt add a date and no errors?

我想把假期一分为二,给定中间的日期。

$splitdate = new DateTime($_POST['date']);

// Split date = 2020-08-04
$holiday1end = $holiday2start = $splitdate;

$holiday1end->sub(new DateInterval('P1D'));
$holiday2start->add(new DateInterval('P1D'));

echobr("Holiday 1: ".$holiday1end->format("Y-m-d"));
echobr("Then " . $splitdate->format("Y-m-d"));
echobr("Holiday 1: " . $holiday2start->format("Y-m-d");

这是我得到的输出:

Holiday 1: 2020-08-04
Then 2020-08-04
Holiday 1: 2020-08-04

这没有意义,最初我将 DateInterval 设置为 'P1D' 但那没有用,所以我尝试删除两天,但我仍然没有得到任何更改或错误。我在这里做错了什么?

编辑清楚:$holiday1end 应该比 $splitdate 少一天, $holiday2start 应该比 $splitdate 多一天,但两者都没有改变。

看来当你这样做的时候,

$splitdate = new DateTime('2010-12-31');
$holiday1end = $holiday2start = $splitdate;

$splitdate 中的对象实例作为对其他变量的引用传递。由于您 subtracting 和 adding 的天数相同,因此代码似乎无法正常工作。然而它工作正常但由于同一对象的共享/引用实例,所有效果都适用于同一对象。

但是,如果您执行类似下面的操作,您会注意到日期增加了 1 天(基本上减去了 2 天,然后又增加了 3 天)。

$date = '2010-12-31';

$splitdate = new DateTime($date);
$holiday1end = $holiday2start = $splitdate;

$holiday1end->sub(new DateInterval('P2D'));
$holiday2start->add(new DateInterval('P3D'));

echo "Holiday 1: ".$holiday1end->format("Y-m-d")."\n";
echo "Then " . $splitdate->format("Y-m-d")."\n";
echo "Holiday 2: " . $holiday2start->format("Y-m-d")."\n";

如果将 DateTime 个对象实例分开,您将获得所需的结果。

$date = '2010-12-31';

$splitdate = new DateTime($date);
$holiday1end = new DateTime($date);
$holiday2start = new DateTime($date);

$holiday1end->sub(new DateInterval('P2D'));
$holiday2start->add(new DateInterval('P2D'));

echo "Holiday 1: ".$holiday1end->format("Y-m-d")."\n";
echo "Then " . $splitdate->format("Y-m-d")."\n";
echo "Holiday 1: " . $holiday2start->format("Y-m-d")."\n";

Working Example of above code

Example with 1 Day difference

添加为新答案,而不是改写/改写旧答案。

正如@Álvaro González 在我的另一个回答中所写的 ,在不同变量之间传递对象时,许多语言中的对象的行为与我们所想的有所不同。

引用自PHP.net

One of the key-points of PHP 5 OOP that is often mentioned is that "objects are passed by references by default". This is not completely true. This section rectifies that general thought using some examples.

A PHP reference is an alias, which allows two different variables to write to the same value. As of PHP 5, an object variable doesn't contain the object itself as value anymore. It only contains an object identifier which allows object accessors to find the actual object. When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.

解释:(从这里我能明白什么)

如果 $var1 包含一个对象并且您尝试使用 assignment operator (=) 将 $var2 初始化为 $var1 就像 $var2 = $var1 $var1 的内容被复制(由 value 传递)到 $var2 但根据手册,如果是 $var1$var1 不包含对象本身作为值,只是一个对象标识符,简单来说,指向实际对象.因此,在上述初始化的情况下,$var1 中的 对象标识符 被复制(由 value 传递)到 $var2 和因为现在两个变量 $var1$var2 都包含指向同一个对象的值,所以看起来赋值是由 reference 传递的,而不是由 [= 传递的65=]值.

所以当你这样做时,

$splitdate = new DateTime('2010-12-31');
$holiday1end = $holiday2start = $splitdate;

您实际上是在将同一对象的 对象标识符 复制到其他变量。由于您 subtracting 和 adding 的天数相同,因此所有这些操作都应用于同一对象。代码似乎无法正常工作,但它可以正常工作。

如果您执行类似下面的操作,您会注意到日期增加了 1 天(基本上减去了 2 天,然后又增加了 3 天)。

$date = '2010-12-31';

$splitdate = new DateTime($date);
$holiday1end = $holiday2start = $splitdate;

$holiday1end->sub(new DateInterval('P2D'));
$holiday2start->add(new DateInterval('P3D'));

echo "Holiday 1: ".$holiday1end->format("Y-m-d")."\n";
echo "Then " . $splitdate->format("Y-m-d")."\n";
echo "Holiday 2: " . $holiday2start->format("Y-m-d")."\n";

如果您将 DateTime 个对象实例分开,您将获得所需的结果。

$date = '2010-12-31';

$splitdate = new DateTime($date);
$holiday1end = new DateTime($date);
$holiday2start = new DateTime($date);

$holiday1end->sub(new DateInterval('P2D'));
$holiday2start->add(new DateInterval('P2D'));

echo "Holiday 1: ".$holiday1end->format("Y-m-d")."\n";
echo "Then " . $splitdate->format("Y-m-d")."\n";
echo "Holiday 1: " . $holiday2start->format("Y-m-d")."\n";

Working Example of above code

Example with 1 Day difference

如果要复制对象本身,可以使用 clone,它会生成对象的 浅拷贝 。因此,在 clone.

问题中使用示例代码
$date = '2010-12-31';

$splitdate = new DateTime($date);

// $holiday1end = clone $splitdate;
// $holiday2start = clone $splitdate;

// OR
// $holiday1end = clone $splitdate;
// $holiday2start = clone $holiday1end;

// OR in one line
$holiday2start = clone $holiday1end = clone $splitdate;

$holiday1end->sub(new DateInterval('P2D'));
$holiday2start->add(new DateInterval('P2D'));

echo "Holiday 1: ".$holiday1end->format("Y-m-d")."\n";
echo "Then " . $splitdate->format("Y-m-d")."\n";
echo "Holiday 2: " . $holiday2start->format("Y-m-d")."\n";

您得到了想要的结果(Example)。