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

From: Date: Tue, 24 Oct 2017 07:52:05 +0000
Subject: Bug #50559 [Asn->Opn]: Clone is not implemented for DateInterval and DatePeriod
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-212165@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:         kalle@php.net
 Reported by:        sr at emini dot dk
 Summary:            Clone is not implemented for DateInterval and
                     DatePeriod
-Status:             Assigned
+Status:             Open
 Type:               Bug
 Package:            Date/time related
 Operating System:   Fedora 10
 PHP Version:        5.3.1
-Assigned To:        derick
+Assigned To:        
 Block user comment: N
 Private report:     N



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


Thread (12 messages)

« previous php.bugs (#212165) next »