1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Merged pull request #12413

This commit is contained in:
Derick Rethans
2023-11-22 15:25:06 +00:00
6 changed files with 415 additions and 3 deletions

3
NEWS
View File

@@ -5,6 +5,9 @@ PHP NEWS
Core:
. Added zend_call_stack_get implementation for NetBSD. (David Carlier)
Date:
. Added DateTime[Immutable]::createFromTimestamp. (Marc Bennewitz)
DOM:
. Added DOMNode::compareDocumentPosition(). (nielsdos)
. Implement #53655 (Improve speed of DOMNode::C14N() on large XML documents).

View File

@@ -2500,6 +2500,49 @@ PHPAPI bool php_date_initialize(php_date_obj *dateobj, const char *time_str, siz
return 1;
} /* }}} */
PHPAPI void php_date_initialize_from_ts_long(php_date_obj *dateobj, zend_long sec, int usec) /* {{{ */
{
dateobj->time = timelib_time_ctor();
dateobj->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
timelib_unixtime2gmt(dateobj->time, (timelib_sll)sec);
timelib_update_ts(dateobj->time, NULL);
php_date_set_time_fraction(dateobj->time, usec);
} /* }}} */
PHPAPI bool php_date_initialize_from_ts_double(php_date_obj *dateobj, double ts) /* {{{ */
{
double sec_dval = trunc(ts);
zend_long sec;
int usec;
if (UNEXPECTED(isnan(sec_dval)
|| sec_dval >= (double)TIMELIB_LONG_MAX
|| sec_dval < (double)TIMELIB_LONG_MIN
)) {
zend_throw_error(
date_ce_date_range_error,
"Seconds must be a finite number between " TIMELIB_LONG_FMT " and " TIMELIB_LONG_FMT ", %g given",
TIMELIB_LONG_MIN,
TIMELIB_LONG_MAX,
sec_dval
);
return false;
}
sec = (zend_long)sec_dval;
usec = (int)(fmod(ts, 1) * 1000000);
if (UNEXPECTED(usec < 0)) {
sec = sec - 1;
usec = 1000000 + usec;
}
php_date_initialize_from_ts_long(dateobj, sec, usec);
return true;
} /* }}} */
/* {{{ Returns new DateTime object */
PHP_FUNCTION(date_create)
{
@@ -2564,7 +2607,7 @@ PHP_FUNCTION(date_create_from_format)
}
/* }}} */
/* {{{ Returns new DateTime object formatted according to the specified format */
/* {{{ Returns new DateTimeImmutable object formatted according to the specified format */
PHP_FUNCTION(date_create_immutable_from_format)
{
zval *timezone_object = NULL;
@@ -2662,6 +2705,39 @@ PHP_METHOD(DateTime, createFromInterface)
}
/* }}} */
/* {{{ Creates new DateTime object from given unix timetamp */
PHP_METHOD(DateTime, createFromTimestamp)
{
zval *value;
zval new_object;
php_date_obj *new_dateobj;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_NUMBER(value)
ZEND_PARSE_PARAMETERS_END();
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, &new_object);
new_dateobj = Z_PHPDATE_P(&new_object);
switch (Z_TYPE_P(value)) {
case IS_LONG:
php_date_initialize_from_ts_long(new_dateobj, Z_LVAL_P(value), 0);
break;
case IS_DOUBLE:
if (!php_date_initialize_from_ts_double(new_dateobj, Z_DVAL_P(value))) {
zval_ptr_dtor(&new_object);
RETURN_THROWS();
}
break;
EMPTY_SWITCH_DEFAULT_CASE();
}
RETURN_OBJ(Z_OBJ(new_object));
}
/* }}} */
/* {{{ Creates new DateTimeImmutable object from an existing mutable DateTime object. */
PHP_METHOD(DateTimeImmutable, createFromMutable)
{
@@ -2704,6 +2780,39 @@ PHP_METHOD(DateTimeImmutable, createFromInterface)
}
/* }}} */
/* {{{ Creates new DateTimeImmutable object from given unix timestamp */
PHP_METHOD(DateTimeImmutable, createFromTimestamp)
{
zval *value;
zval new_object;
php_date_obj *new_dateobj;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_NUMBER(value)
ZEND_PARSE_PARAMETERS_END();
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, &new_object);
new_dateobj = Z_PHPDATE_P(&new_object);
switch (Z_TYPE_P(value)) {
case IS_LONG:
php_date_initialize_from_ts_long(new_dateobj, Z_LVAL_P(value), 0);
break;
case IS_DOUBLE:
if (!php_date_initialize_from_ts_double(new_dateobj, Z_DVAL_P(value))) {
zval_ptr_dtor(&new_object);
RETURN_THROWS();
}
break;
EMPTY_SWITCH_DEFAULT_CASE();
}
RETURN_OBJ(Z_OBJ(new_object));
}
/* }}} */
static bool php_date_initialize_from_hash(php_date_obj **dateobj, HashTable *myht)
{
zval *z_date;

View File

@@ -142,6 +142,7 @@ PHPAPI zend_class_entry *php_date_get_period_ce(void);
PHPAPI zval *php_date_instantiate(zend_class_entry *pce, zval *object);
PHPAPI bool php_date_initialize(php_date_obj *dateobj, const char *time_str, size_t time_str_len, const char *format, zval *timezone_object, int flags);
PHPAPI void php_date_initialize_from_ts_long(php_date_obj *dateobj, zend_long sec, int usec);
PHPAPI bool php_date_initialize_from_ts_double(php_date_obj *dateobj, double ts);
#endif /* PHP_DATE_H */

View File

@@ -362,6 +362,9 @@ class DateTime implements DateTimeInterface
*/
public static function createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null): DateTime|false {}
/** @tentative-return-type */
public static function createFromTimestamp(int|float $timestamp): static {}
/**
* @return array<string, int|array>|false
* @tentative-return-type
@@ -466,6 +469,9 @@ class DateTimeImmutable implements DateTimeInterface
*/
public static function createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null): DateTimeImmutable|false {}
/** @tentative-return-type */
public static function createFromTimestamp(int|float $timestamp): static {}
/**
* @return array<string, int|array>|false
* @tentative-return-type

View File

@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 0f204ac6646be79b515189a384fce9bcea9a4f42 */
* Stub hash: 1445f6053da5ca9dc7bb618f2eadc4a8ea56a15f */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_strtotime, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0)
@@ -280,6 +280,10 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_DateTime_cre
ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, timezone, DateTimeZone, 1, "null")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTime_createFromTimestamp, 0, 1, IS_STATIC, 0)
ZEND_ARG_TYPE_MASK(0, timestamp, MAY_BE_LONG|MAY_BE_DOUBLE, NULL)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_DateTime_getLastErrors, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_END_ARG_INFO()
@@ -348,6 +352,8 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_DateTimeImmu
ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, timezone, DateTimeZone, 1, "null")
ZEND_END_ARG_INFO()
#define arginfo_class_DateTimeImmutable_createFromTimestamp arginfo_class_DateTime_createFromTimestamp
#define arginfo_class_DateTimeImmutable_getLastErrors arginfo_class_DateTime_getLastErrors
#define arginfo_class_DateTimeImmutable_format arginfo_class_DateTimeInterface_format
@@ -554,6 +560,7 @@ ZEND_METHOD(DateTime, __wakeup);
ZEND_METHOD(DateTime, __set_state);
ZEND_METHOD(DateTime, createFromImmutable);
ZEND_METHOD(DateTime, createFromInterface);
ZEND_METHOD(DateTime, createFromTimestamp);
ZEND_METHOD(DateTime, modify);
ZEND_METHOD(DateTime, sub);
ZEND_METHOD(DateTimeImmutable, __construct);
@@ -561,6 +568,7 @@ ZEND_METHOD(DateTimeImmutable, __serialize);
ZEND_METHOD(DateTimeImmutable, __unserialize);
ZEND_METHOD(DateTimeImmutable, __wakeup);
ZEND_METHOD(DateTimeImmutable, __set_state);
ZEND_METHOD(DateTimeImmutable, createFromTimestamp);
ZEND_METHOD(DateTimeImmutable, modify);
ZEND_METHOD(DateTimeImmutable, add);
ZEND_METHOD(DateTimeImmutable, sub);
@@ -670,6 +678,7 @@ static const zend_function_entry class_DateTime_methods[] = {
ZEND_ME(DateTime, createFromImmutable, arginfo_class_DateTime_createFromImmutable, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_ME(DateTime, createFromInterface, arginfo_class_DateTime_createFromInterface, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_ME_MAPPING(createFromFormat, date_create_from_format, arginfo_class_DateTime_createFromFormat, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_ME(DateTime, createFromTimestamp, arginfo_class_DateTime_createFromTimestamp, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_ME_MAPPING(getLastErrors, date_get_last_errors, arginfo_class_DateTime_getLastErrors, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_ME_MAPPING(format, date_format, arginfo_class_DateTime_format, ZEND_ACC_PUBLIC)
ZEND_ME(DateTime, modify, arginfo_class_DateTime_modify, ZEND_ACC_PUBLIC)
@@ -695,6 +704,7 @@ static const zend_function_entry class_DateTimeImmutable_methods[] = {
ZEND_ME(DateTimeImmutable, __wakeup, arginfo_class_DateTimeImmutable___wakeup, ZEND_ACC_PUBLIC)
ZEND_ME(DateTimeImmutable, __set_state, arginfo_class_DateTimeImmutable___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_ME_MAPPING(createFromFormat, date_create_immutable_from_format, arginfo_class_DateTimeImmutable_createFromFormat, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_ME(DateTimeImmutable, createFromTimestamp, arginfo_class_DateTimeImmutable_createFromTimestamp, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_ME_MAPPING(getLastErrors, date_get_last_errors, arginfo_class_DateTimeImmutable_getLastErrors, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_ME_MAPPING(format, date_format, arginfo_class_DateTimeImmutable_format, ZEND_ACC_PUBLIC)
ZEND_ME_MAPPING(getTimezone, date_timezone_get, arginfo_class_DateTimeImmutable_getTimezone, ZEND_ACC_PUBLIC)

View File

@@ -0,0 +1,283 @@
--TEST--
Tests for DateTime[Immutable]::createFromTimestamp
--INI--
date.timezone=Europe/London
--FILE--
<?php
class MyDateTime extends DateTime {};
class MyDateTimeImmutable extends DateTimeImmutable {};
define('MAX_32BIT', 2147483647);
define('MIN_32BIT', -2147483648);
$timestamps = array(
1696883232,
-1696883232,
1696883232.013981,
-1696883232.013981,
0.123456,
-0.123456,
0,
0.0,
-0.0,
MAX_32BIT,
MIN_32BIT,
MIN_32BIT - 0.5,
PHP_INT_MAX + 1024.0,
PHP_INT_MIN - 1025.0,
NAN,
+INF,
-INF
);
foreach ($timestamps as $ts) {
echo 'DateTime::createFromTimestamp(' . var_export($ts, true) . '): ';
try {
var_dump(DateTime::createFromTimestamp($ts));
} catch (Throwable $e) {
echo get_class($e) . ': ' . $e->getMessage() . "\n";
}
echo 'DateTimeImmutable::createFromTimestamp(' . var_export($ts, true) . '): ';
try {
var_dump(DateTimeImmutable::createFromTimestamp($ts));
} catch (Throwable $e) {
echo get_class($e) . ': ' . $e->getMessage() . "\n";
}
}
echo 'MyDateTime::createFromTimestamp(' . var_export(0, true) . '): ';
try {
var_dump(MyDateTime::createFromTimestamp(0));
} catch (Throwable $e) {
echo get_class($e) . ': ' . $e->getMessage() . "\n";
}
echo 'MyDateTimeImmutable::createFromTimestamp(' . var_export(0, true) . '): ';
try {
var_dump(MyDateTimeImmutable::createFromTimestamp(0));
} catch (Throwable $e) {
echo get_class($e) . ': ' . $e->getMessage() . "\n";
}
?>
--EXPECTF--
DateTime::createFromTimestamp(1696883232): object(DateTime)#%d (3) {
["date"]=>
string(26) "2023-10-09 20:27:12.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTimeImmutable::createFromTimestamp(1696883232): object(DateTimeImmutable)#%d (3) {
["date"]=>
string(26) "2023-10-09 20:27:12.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTime::createFromTimestamp(-1696883232): object(DateTime)#%d (3) {
["date"]=>
string(26) "1916-03-25 03:32:48.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTimeImmutable::createFromTimestamp(-1696883232): object(DateTimeImmutable)#%d (3) {
["date"]=>
string(26) "1916-03-25 03:32:48.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTime::createFromTimestamp(1696883232.013981): object(DateTime)#%d (3) {
["date"]=>
string(26) "2023-10-09 20:27:12.013981"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTimeImmutable::createFromTimestamp(1696883232.013981): object(DateTimeImmutable)#%d (3) {
["date"]=>
string(26) "2023-10-09 20:27:12.013981"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTime::createFromTimestamp(-1696883232.013981): object(DateTime)#%d (3) {
["date"]=>
string(26) "1916-03-25 03:32:47.986019"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTimeImmutable::createFromTimestamp(-1696883232.013981): object(DateTimeImmutable)#%d (3) {
["date"]=>
string(26) "1916-03-25 03:32:47.986019"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTime::createFromTimestamp(0.123456): object(DateTime)#%d (3) {
["date"]=>
string(26) "1970-01-01 00:00:00.123456"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTimeImmutable::createFromTimestamp(0.123456): object(DateTimeImmutable)#%d (3) {
["date"]=>
string(26) "1970-01-01 00:00:00.123456"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTime::createFromTimestamp(-0.123456): object(DateTime)#%d (3) {
["date"]=>
string(26) "1969-12-31 23:59:59.876544"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTimeImmutable::createFromTimestamp(-0.123456): object(DateTimeImmutable)#%d (3) {
["date"]=>
string(26) "1969-12-31 23:59:59.876544"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTime::createFromTimestamp(0): object(DateTime)#%d (3) {
["date"]=>
string(26) "1970-01-01 00:00:00.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTimeImmutable::createFromTimestamp(0): object(DateTimeImmutable)#%d (3) {
["date"]=>
string(26) "1970-01-01 00:00:00.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTime::createFromTimestamp(0.0): object(DateTime)#%d (3) {
["date"]=>
string(26) "1970-01-01 00:00:00.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTimeImmutable::createFromTimestamp(0.0): object(DateTimeImmutable)#%d (3) {
["date"]=>
string(26) "1970-01-01 00:00:00.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTime::createFromTimestamp(-0.0): object(DateTime)#%d (3) {
["date"]=>
string(26) "1970-01-01 00:00:00.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTimeImmutable::createFromTimestamp(-0.0): object(DateTimeImmutable)#%d (3) {
["date"]=>
string(26) "1970-01-01 00:00:00.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTime::createFromTimestamp(2147483647): object(DateTime)#%d (3) {
["date"]=>
string(26) "2038-01-19 03:14:07.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTimeImmutable::createFromTimestamp(2147483647): object(DateTimeImmutable)#%d (3) {
["date"]=>
string(26) "2038-01-19 03:14:07.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTime::createFromTimestamp(-2147483648): object(DateTime)#%d (3) {
["date"]=>
string(26) "1901-12-13 20:45:52.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTimeImmutable::createFromTimestamp(-2147483648): object(DateTimeImmutable)#%d (3) {
["date"]=>
string(26) "1901-12-13 20:45:52.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTime::createFromTimestamp(-2147483648.5): object(DateTime)#%d (3) {
["date"]=>
string(26) "1901-12-13 20:45:51.500000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTimeImmutable::createFromTimestamp(-2147483648.5): object(DateTimeImmutable)#%d (3) {
["date"]=>
string(26) "1901-12-13 20:45:51.500000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
DateTime::createFromTimestamp(%f): DateRangeError: Seconds must be a finite number between %i and %i, %f given
DateTimeImmutable::createFromTimestamp(%f): DateRangeError: Seconds must be a finite number between %i and %i, %f given
DateTime::createFromTimestamp(%f): DateRangeError: Seconds must be a finite number between %i and %i, %f given
DateTimeImmutable::createFromTimestamp(%f): DateRangeError: Seconds must be a finite number between %i and %i, %f given
DateTime::createFromTimestamp(NAN): DateRangeError: Seconds must be a finite number between %i and %i, NAN given
DateTimeImmutable::createFromTimestamp(NAN): DateRangeError: Seconds must be a finite number between %i and %i, NAN given
DateTime::createFromTimestamp(INF): DateRangeError: Seconds must be a finite number between %i and %i, INF given
DateTimeImmutable::createFromTimestamp(INF): DateRangeError: Seconds must be a finite number between %i and %i, INF given
DateTime::createFromTimestamp(-INF): DateRangeError: Seconds must be a finite number between %i and %i, -INF given
DateTimeImmutable::createFromTimestamp(-INF): DateRangeError: Seconds must be a finite number between %i and %i, -INF given
MyDateTime::createFromTimestamp(0): object(MyDateTime)#%d (3) {
["date"]=>
string(26) "1970-01-01 00:00:00.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}
MyDateTimeImmutable::createFromTimestamp(0): object(MyDateTimeImmutable)#%d (3) {
["date"]=>
string(26) "1970-01-01 00:00:00.000000"
["timezone_type"]=>
int(1)
["timezone"]=>
string(6) "+00:00"
}