Skip to content

Commit 90434d7

Browse files
committed
Fixed bug #60302: DateTime::createFromFormat should new static(), not new self()
Also fixes similar issues for DateTimeImmutable::createFromFormat, DateTime::createFromImmmutable, DateTime::createFromInterface, DateTimeImmutable::createFromMutable, and DateTimeImmutable::createFromInterface.
1 parent 6b7e2f0 commit 90434d7

12 files changed

+264
-8
lines changed

NEWS

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ PHP NEWS
1010
. Fixed bug #79897 (Promoted constructor params with attribs cause crash).
1111
(Deus Kane)
1212

13+
- Date:
14+
. Fixed bug #60302 (DateTime::createFromFormat should new static(), not new
15+
self()). (Derick)
16+
1317
- JIT:
1418
. Fixed bug #79864 (JIT segfault in Symfony OptionsResolver). (Dmitry)
1519
. Fixed bug #79888 (Incorrect execution with JIT enabled). (Dmitry)

ext/date/php_date.c

+7-7
Original file line numberDiff line numberDiff line change
@@ -2292,7 +2292,7 @@ PHP_FUNCTION(date_create)
22922292
}
22932293
/* }}} */
22942294

2295-
/* {{{ Returns new DateTime object */
2295+
/* {{{ Returns new DateTimeImmutable object */
22962296
PHP_FUNCTION(date_create_immutable)
22972297
{
22982298
zval *timezone_object = NULL;
@@ -2327,7 +2327,7 @@ PHP_FUNCTION(date_create_from_format)
23272327
Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
23282328
ZEND_PARSE_PARAMETERS_END();
23292329

2330-
php_date_instantiate(date_ce_date, return_value);
2330+
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value);
23312331
if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, format_str, timezone_object, 0)) {
23322332
zval_ptr_dtor(return_value);
23332333
RETURN_FALSE;
@@ -2349,7 +2349,7 @@ PHP_FUNCTION(date_create_immutable_from_format)
23492349
Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
23502350
ZEND_PARSE_PARAMETERS_END();
23512351

2352-
php_date_instantiate(date_ce_immutable, return_value);
2352+
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value);
23532353
if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, format_str, timezone_object, 0)) {
23542354
zval_ptr_dtor(return_value);
23552355
RETURN_FALSE;
@@ -2408,7 +2408,7 @@ PHP_METHOD(DateTime, createFromImmutable)
24082408
Z_PARAM_OBJECT_OF_CLASS(datetimeimmutable_object, date_ce_immutable)
24092409
ZEND_PARSE_PARAMETERS_END();
24102410

2411-
php_date_instantiate(date_ce_date, return_value);
2411+
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value);
24122412
old_obj = Z_PHPDATE_P(datetimeimmutable_object);
24132413
new_obj = Z_PHPDATE_P(return_value);
24142414

@@ -2427,7 +2427,7 @@ PHP_METHOD(DateTime, createFromInterface)
24272427
Z_PARAM_OBJECT_OF_CLASS(datetimeinterface_object, date_ce_interface)
24282428
ZEND_PARSE_PARAMETERS_END();
24292429

2430-
php_date_instantiate(date_ce_date, return_value);
2430+
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value);
24312431
old_obj = Z_PHPDATE_P(datetimeinterface_object);
24322432
new_obj = Z_PHPDATE_P(return_value);
24332433

@@ -2446,7 +2446,7 @@ PHP_METHOD(DateTimeImmutable, createFromMutable)
24462446
Z_PARAM_OBJECT_OF_CLASS(datetime_object, date_ce_date)
24472447
ZEND_PARSE_PARAMETERS_END();
24482448

2449-
php_date_instantiate(date_ce_immutable, return_value);
2449+
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value);
24502450
old_obj = Z_PHPDATE_P(datetime_object);
24512451
new_obj = Z_PHPDATE_P(return_value);
24522452

@@ -2465,7 +2465,7 @@ PHP_METHOD(DateTimeImmutable, createFromInterface)
24652465
Z_PARAM_OBJECT_OF_CLASS(datetimeinterface_object, date_ce_interface)
24662466
ZEND_PARSE_PARAMETERS_END();
24672467

2468-
php_date_instantiate(date_ce_immutable, return_value);
2468+
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value);
24692469
old_obj = Z_PHPDATE_P(datetimeinterface_object);
24702470
new_obj = Z_PHPDATE_P(return_value);
24712471

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
--TEST--
2+
Tests for DateTimeImmutable::createFromInterface inheritance
3+
--INI--
4+
date.timezone=Europe/London
5+
--FILE--
6+
<?php
7+
class MyDateTimeImmutable extends DateTimeImmutable {}
8+
9+
$current = "2014-03-02 16:24:08";
10+
11+
$i = MyDateTimeImmutable::createFromInterface( date_create( $current ) );
12+
var_dump( $i );
13+
14+
$i = MyDateTimeImmutable::createFromInterface( date_create_immutable( $current ) );
15+
var_dump( $i );
16+
17+
$current = "2019-12-16 15:06:46 CET";
18+
19+
$i = MyDateTimeImmutable::createFromInterface( date_create( $current ) );
20+
var_dump( $i );
21+
22+
$i = MyDateTimeImmutable::createFromInterface( date_create_immutable( $current ) );
23+
var_dump( $i );
24+
25+
$current = "2019-12-16 15:08:20 +0100";
26+
27+
$i = MyDateTimeImmutable::createFromInterface( date_create( $current ) );
28+
var_dump( $i );
29+
30+
$i = MyDateTimeImmutable::createFromInterface( date_create_immutable( $current ) );
31+
var_dump( $i );
32+
?>
33+
--EXPECTF--
34+
object(MyDateTimeImmutable)#%d (3) {
35+
["date"]=>
36+
string(26) "2014-03-02 16:24:08.000000"
37+
["timezone_type"]=>
38+
int(3)
39+
["timezone"]=>
40+
string(13) "Europe/London"
41+
}
42+
object(MyDateTimeImmutable)#%d (3) {
43+
["date"]=>
44+
string(26) "2014-03-02 16:24:08.000000"
45+
["timezone_type"]=>
46+
int(3)
47+
["timezone"]=>
48+
string(13) "Europe/London"
49+
}
50+
object(MyDateTimeImmutable)#%d (3) {
51+
["date"]=>
52+
string(26) "2019-12-16 15:06:46.000000"
53+
["timezone_type"]=>
54+
int(2)
55+
["timezone"]=>
56+
string(3) "CET"
57+
}
58+
object(MyDateTimeImmutable)#%d (3) {
59+
["date"]=>
60+
string(26) "2019-12-16 15:06:46.000000"
61+
["timezone_type"]=>
62+
int(2)
63+
["timezone"]=>
64+
string(3) "CET"
65+
}
66+
object(MyDateTimeImmutable)#%d (3) {
67+
["date"]=>
68+
string(26) "2019-12-16 15:08:20.000000"
69+
["timezone_type"]=>
70+
int(1)
71+
["timezone"]=>
72+
string(6) "+01:00"
73+
}
74+
object(MyDateTimeImmutable)#%d (3) {
75+
["date"]=>
76+
string(26) "2019-12-16 15:08:20.000000"
77+
["timezone_type"]=>
78+
int(1)
79+
["timezone"]=>
80+
string(6) "+01:00"
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
Tests for inherited DateTimeImmutable::createFromMutable
3+
--INI--
4+
date.timezone=Europe/London
5+
--FILE--
6+
<?php
7+
class MyDateTimeImmutable extends DateTimeImmutable {}
8+
9+
$current = "2014-03-02 16:24:08";
10+
11+
$i = MyDateTimeImmutable::createFromMutable( date_create( $current ) );
12+
var_dump( $i );
13+
14+
try {
15+
MyDateTimeImmutable::createFromMutable( date_create_immutable( $current ) );
16+
} catch (TypeError $e) {
17+
echo $e->getMessage(), "\n";
18+
}
19+
?>
20+
--EXPECTF--
21+
object(MyDateTimeImmutable)#%d (3) {
22+
["date"]=>
23+
string(26) "2014-03-02 16:24:08.000000"
24+
["timezone_type"]=>
25+
int(3)
26+
["timezone"]=>
27+
string(13) "Europe/London"
28+
}
29+
DateTimeImmutable::createFromMutable(): Argument #1 ($object) must be of type DateTime, DateTimeImmutable given

ext/date/tests/DateTime_createFromImmutable.phpt renamed to ext/date/tests/DateTime_createFromImmutable-001.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Tests for DateTime::createFromImmutable.
2+
Tests for DateTime::createFromImmutable
33
--INI--
44
date.timezone=Europe/London
55
--FILE--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
Tests for inherited DateTime::createFromImmutable
3+
--INI--
4+
date.timezone=Europe/London
5+
--FILE--
6+
<?php
7+
class MyDateTime extends DateTime {}
8+
9+
$current = "2014-03-02 16:24:08";
10+
$i = date_create_immutable( $current );
11+
12+
$m = MyDateTime::createFromImmutable( $i );
13+
var_dump( $m );
14+
15+
$m->modify('+ 1 hour');
16+
17+
var_dump( $i->format('Y-m-d H:i:s') === $current );
18+
19+
try {
20+
MyDateTime::createFromImmutable( date_create( $current ) );
21+
} catch (TypeError $e) {
22+
echo $e->getMessage(), "\n";
23+
}
24+
?>
25+
--EXPECTF--
26+
object(MyDateTime)#%d (3) {
27+
["date"]=>
28+
string(26) "2014-03-02 16:24:08.000000"
29+
["timezone_type"]=>
30+
int(3)
31+
["timezone"]=>
32+
string(13) "Europe/London"
33+
}
34+
bool(true)
35+
DateTime::createFromImmutable(): Argument #1 ($object) must be of type DateTimeImmutable, DateTime given
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
--TEST--
2+
Tests for DateTime::createFromInterface with inheritance
3+
--INI--
4+
date.timezone=Europe/London
5+
--FILE--
6+
<?php
7+
class MyDateTime extends DateTime {}
8+
9+
$current = "2014-03-02 16:24:08";
10+
11+
$i = MyDateTime::createFromInterface( date_create( $current ) );
12+
var_dump( $i );
13+
14+
$i = MyDateTime::createFromInterface( date_create_immutable( $current ) );
15+
var_dump( $i );
16+
17+
$current = "2019-12-16 15:06:46 CET";
18+
19+
$i = MyDateTime::createFromInterface( date_create( $current ) );
20+
var_dump( $i );
21+
22+
$i = MyDateTime::createFromInterface( date_create_immutable( $current ) );
23+
var_dump( $i );
24+
25+
$current = "2019-12-16 15:08:20 +0100";
26+
27+
$i = MyDateTime::createFromInterface( date_create( $current ) );
28+
var_dump( $i );
29+
30+
$i = MyDateTime::createFromInterface( date_create_immutable( $current ) );
31+
var_dump( $i );
32+
?>
33+
--EXPECTF--
34+
object(MyDateTime)#%d (3) {
35+
["date"]=>
36+
string(26) "2014-03-02 16:24:08.000000"
37+
["timezone_type"]=>
38+
int(3)
39+
["timezone"]=>
40+
string(13) "Europe/London"
41+
}
42+
object(MyDateTime)#%d (3) {
43+
["date"]=>
44+
string(26) "2014-03-02 16:24:08.000000"
45+
["timezone_type"]=>
46+
int(3)
47+
["timezone"]=>
48+
string(13) "Europe/London"
49+
}
50+
object(MyDateTime)#%d (3) {
51+
["date"]=>
52+
string(26) "2019-12-16 15:06:46.000000"
53+
["timezone_type"]=>
54+
int(2)
55+
["timezone"]=>
56+
string(3) "CET"
57+
}
58+
object(MyDateTime)#%d (3) {
59+
["date"]=>
60+
string(26) "2019-12-16 15:06:46.000000"
61+
["timezone_type"]=>
62+
int(2)
63+
["timezone"]=>
64+
string(3) "CET"
65+
}
66+
object(MyDateTime)#%d (3) {
67+
["date"]=>
68+
string(26) "2019-12-16 15:08:20.000000"
69+
["timezone_type"]=>
70+
int(1)
71+
["timezone"]=>
72+
string(6) "+01:00"
73+
}
74+
object(MyDateTime)#%d (3) {
75+
["date"]=>
76+
string(26) "2019-12-16 15:08:20.000000"
77+
["timezone_type"]=>
78+
int(1)
79+
["timezone"]=>
80+
string(6) "+01:00"
81+
}

ext/date/tests/bug60302-001.phpt

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
Test for bug #60302: DateTime::createFromFormat should new static(), not new self()
3+
--FILE--
4+
<?php
5+
6+
class MyDateTime extends DateTime { }
7+
8+
$d = MyDateTime::createFromFormat('Y-m-d', '2011-01-01');
9+
10+
echo get_class($d);
11+
?>
12+
--EXPECT--
13+
MyDateTime

ext/date/tests/bug60302-002.phpt

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
Test for bug #60302: DateTimeImmutable::createFromFormat should new static(), not new self()
3+
--FILE--
4+
<?php
5+
6+
class MyDateTime extends DateTimeImmutable { }
7+
8+
$d = MyDateTime::createFromFormat('Y-m-d', '2011-01-01');
9+
10+
echo get_class($d);
11+
?>
12+
--EXPECT--
13+
MyDateTime

0 commit comments

Comments
 (0)