Bug #50559 [Opn->Csd]: Clone is not implemented for DateInterval and DatePeriod

From: Date: Sun, 05 Aug 2018 01:34:36 +0000
Subject: Bug #50559 [Opn->Csd]: Clone is not implemented for DateInterval and DatePeriod
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-216590@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=50559&edit=1 ID: 50559 Updated by: carusogabriel@php.net Reported by: sr at emini dot dk Summary: Clone is not implemented for DateInterval and DatePeriod -Status: Open +Status: Closed Type: Bug Package: Date/time related Operating System: Fedora 10 PHP Version: 5.3.1 -Assigned To: +Assigned To: carusogabriel Block user comment: N Private report: N New Comment: Closing as it was implemented via http://git.php.net/?p=php-src.git;a=commit;h=48598a23. https://3v4l.org/HA8kn Previous Comments: ------------------------------------------------------------------------ [2017-06-30 21:49:09] anatoliy at ukhvanovy dot name Also, if you don't wanna deal with manual coping all the fields like in example above, you may copy a \DateInterval object indirectly, using the inverse operations \DateTime::add() and \DateTime::diff() as shown below: <?php class CloneDateInterval { /** * @var \DateTime */ private static $midnight; private static function getMidnight(): \DateTime { if (self::$midnight === null) { self::$midnight = new \DateTime('midnight'); } return clone self::$midnight; } public static function makeClone(\DateInterval $dateInterval): \DateInterval { return self::getMidnight()->diff(self::getMidnight()->add($dateInterval)); } } ?> Although, maybe this method is not as computationally efficient as the one from above, but it definitely is an interesting alternative, at least from theoretical point of view. :D ------------------------------------------------------------------------ [2017-05-26 12:47:01] cmb@php.net Related To: Bug #74639 ------------------------------------------------------------------------ [2016-10-30 16:12:33] anatoliy at ukhvanovy dot name The previous example doesn't work. The cloned copy can be var_export'ed correctly, that's true. But when you try to add it to a DateTime instance, the datetime won't change at all. Thus, cloned copies are broken. That's why I use another workaround: <?php class CloneDateInterval { /** * @param \DateInterval $originalInstance * @return \DateInterval */ public static function buildClone(\DateInterval $originalInstance) { $copy = new \DateInterval('P0D'); foreach ($originalInstance as $propertyName => $propertyValue) { $copy->{$propertyName} = $propertyValue; } return $copy; } } ?> This one works fine: $copy = CloneDateTime::buildClone($originalDateInterval); $datetime->add($copy); //OK ------------------------------------------------------------------------ [2016-10-30 15:08:43] anatoliy at ukhvanovy dot name There's a WORKAROUND. If you var_export the instance, then it won't be empty anymore, and you can clone it. Consider the following code: <?php header('Content-Type:text/plain'); $originalInstance = new DateInterval('P1D'); // Original instance is not initialized yet. // You cannot clone it now, otherwise you'll get an empty copy. $copyCreatedBeforeOriginalInstanceIsInitialized = clone $originalInstance; echo PHP_EOL, 'This copy is empty: '; var_export($copyCreatedBeforeOriginalInstanceIsInitialized); // Now, let's initialize original instance by var_export'ing it. // We don't want to output the var_export's result - // it is used only to initialize our instance, not to output it. $doNotEchoVarExport = true; var_export($originalInstance, $doNotEchoVarExport); // That's all! For now, original instance is already initialized, // and we may clone it — we'll get correct copy. $copyCreatedAfterOriginalInstanceIsInitialized = clone $originalInstance; // Now, let's see what we've got: echo PHP_EOL, 'Original instance is OK: '; var_export($originalInstance); echo PHP_EOL, 'Empty copy is still empty: '; var_export($copyCreatedBeforeOriginalInstanceIsInitialized); echo PHP_EOL, 'Correct copy is OK: '; var_export($copyCreatedAfterOriginalInstanceIsInitialized); // DateInterval behaves like Schrödinger's cat: // the action of observation affects the phenomenon being observed. // (var_export'ing the state of DateInterval affects its state.) ?> The code above produces the following output: This copy is empty: DateInterval::__set_state(array( )) Original instance is OK: DateInterval::__set_state(array( 'y' => 0, 'm' => 0, 'd' => 1, 'h' => 0, 'i' => 0, 's' => 0, 'weekday' => 0, 'weekday_behavior' => 0, 'first_last_day_of' => 0, 'invert' => 0, 'days' => false, 'special_type' => 0, 'special_amount' => 0, 'have_weekday_relative' => 0, 'have_special_relative' => 0, )) Empty copy is still empty: DateInterval::__set_state(array( )) Correct copy is OK: DateInterval::__set_state(array( 'y' => 0, 'm' => 0, 'd' => 1, 'h' => 0, 'i' => 0, 's' => 0, 'weekday' => 0, 'weekday_behavior' => 0, 'first_last_day_of' => 0, 'invert' => 0, 'days' => false, 'special_type' => 0, 'special_amount' => 0, 'have_weekday_relative' => 0, 'have_special_relative' => 0, )) ------------------------------------------------------------------------ [2013-08-07 20:09:36] kofkof at laposte dot net If I swap lines 2 and 3 in the bug description code, this way: $dateInterval1 = new DateInterval('P1D'); var_dump($dateInterval1); $dateInterval2 = clone $dateInterval1; var_dump($dateInterval2); ... then $dateInterval2 is not empty (as displayed by var_dump()). However, when I try to use it: $d = new DateTime(); $d->add($dateInterval2); ... then I get "Warning: DateTime::add(): The DateInterval object has not been correctly initialized by its constructor in..." (PHP 5.4.11 on Mac OS 10.7.5) ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=50559 -- Edit this bug report at https://bugs.php.net/bug.php?id=50559&edit=1

« previous php.bugs (#216590) next »