DateInterval не добавляет дату и никаких ошибок? - PullRequest
0 голосов
/ 07 августа 2020

Я пытаюсь разделить праздник на две части, учитывая дату посередине.

$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, но ни один из них не меняется.

Ответы [ 2 ]

1 голос
/ 07 августа 2020

Кажется, что когда вы это делаете,

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

Экземпляр объекта в $splitdate передается как ссылка на другие переменные. И поскольку вы sub отслеживаете и add используете одинаковое количество дней, кажется, что код не работает. Однако он работает правильно, но из-за общего / указанного экземпляра одного и того же объекта весь эффект переходит к одному и тому же объекту. дни вычитаются, а затем добавляются 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";

Рабочий пример кода выше

Пример с разницей в 1 день

0 голосов
/ 08 августа 2020

Добавление в качестве нового ответа вместо перефразирования / перефразирования старого.

Как прокомментировал @ Álvaro González на мой другой ответ, что объекты на многих языках ведут себя как-то что отличается от того, что мы думаем при передаче объектов между разными переменными.

Цитата из PHP. net

Один из ключевых моментов PHP 5 OOP часто упоминается, что «объекты по умолчанию передаются по ссылкам». Это не совсем так. Этот раздел исправляет эту общую мысль с помощью нескольких примеров.

Ссылка PHP - это псевдоним, который позволяет двум различным переменным записывать одно и то же значение. Начиная с PHP 5, объектная переменная больше не содержит сам объект как значение. Он содержит только идентификатор объекта, который позволяет средствам доступа к объекту находить реальный объект. Когда объект отправляется аргументом, возвращается или назначается другой переменной, разные переменные не являются псевдонимами: они содержат копию идентификатора, который указывает на тот же объект.

Объяснение : (что я могу понять из этого)

Если $var1 содержит объект, и вы пытаетесь инициализировать $var2 с помощью $var1, используя оператор присваивания (= ), например, $var2 = $var1, содержимое $var1 копируется (передается с помощью value ) в $var2, но, как указано в руководстве, в случае $var1, $var1 не содержит сам объект как значение , но простой идентификатор объекта, который , простыми словами, указывает на реальный объект . Таким образом, в случае вышеупомянутой инициализации идентификатор объекта в $var1 копируется (передается значением ) в $var2, и теперь обе переменные $var1, $var2 содержат значение, которое указывает на тот же объект, поэтому кажется, что присваивание действовало как переданное ссылкой , а не значением .

Итак, когда вы это делаете,

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

Фактически вы копируете идентификатор объекта того же объекта в другие переменные. И поскольку вы sub отслеживаете и add используете одинаковое количество дней, все эти операции применяются к одному и тому же объекту. И кажется, что код не работает, однако он работает правильно.

Если вы сделаете что-то вроде ниже, вы заметите, что к дате добавляется 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";

Рабочий пример приведенного выше кода

Пример с разницей в 1 день

Если вы хотите скопировать сам объект, вы можете использовать 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";

, вы получите желаемые результаты ( Пример ).

...