Bug #50559 [Com]: Clone is not implemented for DateInterval and DatePeriod

From: Date: Sun, 30 Oct 2016 15:08:47 +0000
Subject: Bug #50559 [Com]: Clone is not implemented for DateInterval and DatePeriod
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-205072@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 Comment by: anatoliy at ukhvanovy dot name Reported by: sr at emini dot dk Summary: Clone is not implemented for DateInterval and DatePeriod Status: Assigned Type: Bug Package: Date/time related Operating System: Fedora 10 PHP Version: 5.3.1 Assigned To: derick Block user comment: N Private report: N New Comment: 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, )) Previous Comments: ------------------------------------------------------------------------ [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) ------------------------------------------------------------------------ [2011-05-06 11:14:51] giorgio dot liscio at email dot it on windows 7 + apache2 + php 5.3.6 apache crashes when $cl = clone $dateIntervalObject; in any scope, in any function, on an empty page too. i tried to provide a backtrace but something goes wrong i can't convert the generated .dmp file to a readable dump to attach here ------------------------------------------------------------------------ [2010-03-08 10:59:43] yoarvi at gmail dot com Did you forget to attach the script? ------------------------------------------------------------------------ [2010-03-07 20:24:53] derick@php.net This patch causes issues. If I try the attached script I end up in an infinite loop. ------------------------------------------------------------------------ [2010-01-27 13:47:00] yoarvi at gmail dot com The following patch implements the logic to clone DatePeriod and DateInterval objects and also includes a test case: Index: ext/date/php_date.c =================================================================== --- ext/date/php_date.c (revision 293574) +++ ext/date/php_date.c (working copy) @@ -2213,7 +2213,9 @@ zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); - /** FIX ME ADD CLONE STUFF **/ + new_obj->diff = timelib_rel_time_clone(old_obj->diff); + new_obj->initialized = 1; + return new_ov; } @@ -2283,7 +2285,27 @@ zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); - /** FIX ME ADD CLONE STUFF **/ + new_obj->start = timelib_time_ctor(); + *new_obj->start = *old_obj->start; + if (old_obj->start->tz_abbr) { + new_obj->start->tz_abbr = strdup(old_obj->start->tz_abbr); + } + if (old_obj->start->tz_info) { + new_obj->start->tz_info = old_obj->start->tz_info; + } + new_obj->end = timelib_time_ctor(); + *new_obj->end = *old_obj->end; + if (old_obj->end->tz_abbr) { + new_obj->end->tz_abbr = strdup(old_obj->end->tz_abbr); + } + if (old_obj->end->tz_info) { + new_obj->end->tz_info = old_obj->end->tz_info; + } + new_obj->interval = timelib_rel_time_clone(old_obj->interval); + new_obj->recurrences = old_obj->recurrences; + new_obj->include_start_date = old_obj->include_start_date; + new_obj->initialized = 1; + return new_ov; } Index: ext/date/tests/bug50559.phpt =================================================================== --- ext/date/tests/bug50559.phpt (revision 0) +++ ext/date/tests/bug50559.phpt (revision 0) @@ -0,0 +1,131 @@ +--TEST-- +Bug #50559 (Clone is not implemented for DateInterval and DatePeriod) +--FILE-- +<?php +date_default_timezone_set('Asia/Calcutta'); + +# Test DateInterval cloning +$dateInterval1 = new \DateInterval('P1D'); +$dateInterval2 = clone $dateInterval1; +echo "============================\n"; +echo "DateInterval (original)\n"; +var_dump($dateInterval1); +echo "============================\n"; +echo "DateInterval (clone)\n"; +var_dump($dateInterval2); + +# Test DatePeriod cloning +$begin = new DateTime('2007-12-31'); +$end = new DateTime('2009-12-31 23:59:59'); +$interval = DateInterval::createFromDateString('last thursday of next month'); +$datePeriod1 = new \DatePeriod($begin, $interval, $end, + DatePeriod::EXCLUDE_START_DATE); +$datePeriod2 = clone $datePeriod1; + +echo "============================\n"; +echo "DatePeriod (original)\n"; +foreach ($datePeriod1 as $p) { + echo $p->format("l Y-m-d H:i:s\n"); +} + +echo "============================\n"; +echo "DatePeriod (clone)\n"; +foreach ($datePeriod2 as $p) { + echo $p->format("l Y-m-d H:i:s\n"); +} +echo "============================\n"; +?> +--EXPECT-- +============================ +DateInterval (original) +object(DateInterval)#1 (8) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(1) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + int(0) +} +============================ +DateInterval (clone) +object(DateInterval)#2 (8) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(1) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + int(0) +} +============================ +DatePeriod (original) +Thursday 2008-01-31 00:00:00 +Thursday 2008-02-28 00:00:00 +Thursday 2008-03-27 00:00:00 +Thursday 2008-04-24 00:00:00 +Thursday 2008-05-29 00:00:00 +Thursday 2008-06-26 00:00:00 +Thursday 2008-07-31 00:00:00 +Thursday 2008-08-28 00:00:00 +Thursday 2008-09-25 00:00:00 +Thursday 2008-10-30 00:00:00 +Thursday 2008-11-27 00:00:00 +Thursday 2008-12-25 00:00:00 +Thursday 2009-01-29 00:00:00 +Thursday 2009-02-26 00:00:00 +Thursday 2009-03-26 00:00:00 +Thursday 2009-04-30 00:00:00 +Thursday 2009-05-28 00:00:00 +Thursday 2009-06-25 00:00:00 +Thursday 2009-07-30 00:00:00 +Thursday 2009-08-27 00:00:00 +Thursday 2009-09-24 00:00:00 +Thursday 2009-10-29 00:00:00 +Thursday 2009-11-26 00:00:00 +Thursday 2009-12-31 00:00:00 +============================ +DatePeriod (clone) +Thursday 2008-01-31 00:00:00 +Thursday 2008-02-28 00:00:00 +Thursday 2008-03-27 00:00:00 +Thursday 2008-04-24 00:00:00 +Thursday 2008-05-29 00:00:00 +Thursday 2008-06-26 00:00:00 +Thursday 2008-07-31 00:00:00 +Thursday 2008-08-28 00:00:00 +Thursday 2008-09-25 00:00:00 +Thursday 2008-10-30 00:00:00 +Thursday 2008-11-27 00:00:00 +Thursday 2008-12-25 00:00:00 +Thursday 2009-01-29 00:00:00 +Thursday 2009-02-26 00:00:00 +Thursday 2009-03-26 00:00:00 +Thursday 2009-04-30 00:00:00 +Thursday 2009-05-28 00:00:00 +Thursday 2009-06-25 00:00:00 +Thursday 2009-07-30 00:00:00 +Thursday 2009-08-27 00:00:00 +Thursday 2009-09-24 00:00:00 +Thursday 2009-10-29 00:00:00 +Thursday 2009-11-26 00:00:00 +Thursday 2009-12-31 00:00:00 +============================ ------------------------------------------------------------------------ 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 (#205072) next »