summaryrefslogtreecommitdiff
path: root/ext/date/php_date.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/date/php_date.c')
-rw-r--r--ext/date/php_date.c171
1 files changed, 90 insertions, 81 deletions
diff --git a/ext/date/php_date.c b/ext/date/php_date.c
index 35c018e324..dbcd7d8695 100644
--- a/ext/date/php_date.c
+++ b/ext/date/php_date.c
@@ -299,6 +299,10 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_date_method_timestamp_get, 0)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_create_from_mutable, 0, 0, 1)
+ ZEND_ARG_INFO(0, DateTime)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_open, 0, 0, 1)
ZEND_ARG_INFO(0, timezone)
ZEND_END_ARG_INFO()
@@ -495,6 +499,7 @@ const zend_function_entry date_funcs_immutable[] = {
PHP_ME(DateTimeImmutable, setDate, arginfo_date_method_date_set, 0)
PHP_ME(DateTimeImmutable, setISODate, arginfo_date_method_isodate_set, 0)
PHP_ME(DateTimeImmutable, setTimestamp, arginfo_date_method_timestamp_set, 0)
+ PHP_ME(DateTimeImmutable, createFromMutable, arginfo_date_method_create_from_mutable, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_FE_END
};
@@ -2267,7 +2272,7 @@ static zend_object *date_object_clone_timezone(zval *this_ptr TSRMLS_DC) /* {{{
case TIMELIB_ZONETYPE_ABBR:
new_obj->tzi.z.utc_offset = old_obj->tzi.z.utc_offset;
new_obj->tzi.z.dst = old_obj->tzi.z.dst;
- new_obj->tzi.z.abbr = old_obj->tzi.z.abbr;
+ new_obj->tzi.z.abbr = strdup(old_obj->tzi.z.abbr);
break;
}
@@ -2699,6 +2704,34 @@ PHP_METHOD(DateTimeImmutable, __construct)
}
/* }}} */
+/* {{{ proto DateTimeImmutable::createFromMutable(DateTimeZone object)
+ Creates new DateTimeImmutable object from an existing mutable DateTime object.
+*/
+PHP_METHOD(DateTimeImmutable, createFromMutable)
+{
+ zval *datetime_object = NULL;
+ php_date_obj *new_obj = NULL;
+ php_date_obj *old_obj = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O!", &datetime_object, date_ce_date) == FAILURE) {
+ return;
+ }
+
+ php_date_instantiate(date_ce_immutable, return_value TSRMLS_CC);
+ old_obj = Z_PHPDATE_P(datetime_object);
+ new_obj = Z_PHPDATE_P(return_value);
+
+ new_obj->time = timelib_time_ctor();
+ *new_obj->time = *old_obj->time;
+ if (old_obj->time->tz_abbr) {
+ new_obj->time->tz_abbr = strdup(old_obj->time->tz_abbr);
+ }
+ if (old_obj->time->tz_info) {
+ new_obj->time->tz_info = old_obj->time->tz_info;
+ }
+}
+/* }}} */
+
static int php_date_initialize_from_hash(zval *return_value, php_date_obj **dateobj, HashTable *myht TSRMLS_DC) /* {{{ */
{
zval *z_date;
@@ -2735,6 +2768,10 @@ static int php_date_initialize_from_hash(zval *return_value, php_date_obj **date
tzi = php_date_parse_tzfile(Z_STRVAL_P(z_timezone), DATE_TIMEZONEDB TSRMLS_CC);
+ if (tzi == NULL) {
+ return 0;
+ }
+
tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, &tmp_obj TSRMLS_CC));
tzobj->type = TIMELIB_ZONETYPE_ID;
tzobj->tzi.tz = tzi;
@@ -3188,6 +3225,26 @@ PHP_METHOD(DateTimeImmutable, sub)
}
/* }}} */
+static void set_timezone_from_timelib_time(php_timezone_obj *tzobj, timelib_time *t)
+{
+ tzobj->initialized = 1;
+ tzobj->type = t->zone_type;
+ switch (t->zone_type) {
+ case TIMELIB_ZONETYPE_ID:
+ tzobj->tzi.tz = t->tz_info;
+ break;
+ case TIMELIB_ZONETYPE_OFFSET:
+ tzobj->tzi.utc_offset = t->z;
+ break;
+ case TIMELIB_ZONETYPE_ABBR:
+ tzobj->tzi.z.utc_offset = t->z;
+ tzobj->tzi.z.dst = t->dst;
+ tzobj->tzi.z.abbr = strdup(t->tz_abbr);
+ break;
+ }
+}
+
+
/* {{{ proto DateTimeZone date_timezone_get(DateTimeInterface object)
Return new DateTimeZone object relative to give DateTime
*/
@@ -3205,21 +3262,7 @@ PHP_FUNCTION(date_timezone_get)
if (dateobj->time->is_localtime/* && dateobj->time->tz_info*/) {
php_date_instantiate(date_ce_timezone, return_value TSRMLS_CC);
tzobj = Z_PHPTIMEZONE_P(return_value);
- tzobj->initialized = 1;
- tzobj->type = dateobj->time->zone_type;
- switch (dateobj->time->zone_type) {
- case TIMELIB_ZONETYPE_ID:
- tzobj->tzi.tz = dateobj->time->tz_info;
- break;
- case TIMELIB_ZONETYPE_OFFSET:
- tzobj->tzi.utc_offset = dateobj->time->z;
- break;
- case TIMELIB_ZONETYPE_ABBR:
- tzobj->tzi.z.utc_offset = dateobj->time->z;
- tzobj->tzi.z.dst = dateobj->time->dst;
- tzobj->tzi.z.abbr = strdup(dateobj->time->tz_abbr);
- break;
- }
+ set_timezone_from_timelib_time(tzobj, dateobj->time);
} else {
RETURN_FALSE;
}
@@ -3234,11 +3277,18 @@ static void php_date_timezone_set(zval *object, zval *timezone_object, zval *ret
dateobj = Z_PHPDATE_P(object);
DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
tzobj = Z_PHPTIMEZONE_P(timezone_object);
- if (tzobj->type != TIMELIB_ZONETYPE_ID) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only do this for zones with ID for now");
- return;
+
+ switch (tzobj->type) {
+ case TIMELIB_ZONETYPE_OFFSET:
+ timelib_set_timezone_from_offset(dateobj->time, tzobj->tzi.utc_offset);
+ break;
+ case TIMELIB_ZONETYPE_ABBR:
+ timelib_set_timezone_from_abbr(dateobj->time, tzobj->tzi.z);
+ break;
+ case TIMELIB_ZONETYPE_ID:
+ timelib_set_timezone(dateobj->time, tzobj->tzi.tz);
+ break;
}
- timelib_set_timezone(dateobj->time, tzobj->tzi.tz);
timelib_unixtime2local(dateobj->time, dateobj->time->sse);
} /* }}} */
@@ -3563,23 +3613,21 @@ PHP_FUNCTION(date_diff)
}
/* }}} */
-static int timezone_initialize(timelib_tzinfo **tzi, /*const*/ char *tz TSRMLS_DC) /* {{{ */
+static int timezone_initialize(php_timezone_obj *tzobj, /*const*/ char *tz TSRMLS_DC) /* {{{ */
{
- char *tzid;
-
- *tzi = NULL;
-
- if ((tzid = timelib_timezone_id_from_abbr(tz, -1, 0))) {
- *tzi = php_date_parse_tzfile(tzid, DATE_TIMEZONEDB TSRMLS_CC);
+ timelib_time *dummy_t = ecalloc(1, sizeof(timelib_time));
+ int dst, not_found;
+ char *orig_tz = tz;
+
+ dummy_t->z = timelib_parse_zone(&tz, &dst, dummy_t, &not_found, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
+ if (not_found) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad timezone (%s)", orig_tz);
+ efree(dummy_t);
+ return FAILURE;
} else {
- *tzi = php_date_parse_tzfile(tz, DATE_TIMEZONEDB TSRMLS_CC);
- }
-
- if (*tzi) {
+ set_timezone_from_timelib_time(tzobj, dummy_t);
+ efree(dummy_t);
return SUCCESS;
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad timezone (%s)", tz);
- return FAILURE;
}
} /* }}} */
@@ -3590,19 +3638,15 @@ PHP_FUNCTION(timezone_open)
{
char *tz;
int tz_len;
- timelib_tzinfo *tzi = NULL;
php_timezone_obj *tzobj;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &tz, &tz_len) == FAILURE) {
RETURN_FALSE;
}
- if (SUCCESS != timezone_initialize(&tzi, tz TSRMLS_CC)) {
+ tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, return_value TSRMLS_CC));
+ if (SUCCESS != timezone_initialize(tzobj, tz TSRMLS_CC)) {
RETURN_FALSE;
}
- tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, return_value TSRMLS_CC));
- tzobj->type = TIMELIB_ZONETYPE_ID;
- tzobj->tzi.tz = tzi;
- tzobj->initialized = 1;
}
/* }}} */
@@ -3613,18 +3657,13 @@ PHP_METHOD(DateTimeZone, __construct)
{
char *tz;
int tz_len;
- timelib_tzinfo *tzi = NULL;
php_timezone_obj *tzobj;
zend_error_handling error_handling;
zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &tz, &tz_len)) {
- if (SUCCESS == timezone_initialize(&tzi, tz TSRMLS_CC)) {
- tzobj = Z_PHPTIMEZONE_P(getThis());
- tzobj->type = TIMELIB_ZONETYPE_ID;
- tzobj->tzi.tz = tzi;
- tzobj->initialized = 1;
-//??? } else {
+ tzobj = Z_PHPTIMEZONE_P(getThis());
+ if (FAILURE == timezone_initialize(tzobj, tz TSRMLS_CC)) {
//??? ZVAL_NULL(getThis());
}
}
@@ -3636,41 +3675,12 @@ static int php_date_timezone_initialize_from_hash(zval **return_value, php_timez
{
zval *z_timezone;
zval *z_timezone_type;
- timelib_tzinfo *tzi;
- z_timezone_type = zend_hash_str_find(myht, "timezone_type", sizeof("timezone_type")-1);
- if (z_timezone_type) {
- z_timezone = zend_hash_str_find(myht, "timezone", sizeof("timezone")-1);
- if (z_timezone) {
+ if ((z_timezone_type = zend_hash_str_find(myht, "timezone_type", sizeof("timezone_type")-1)) != NULL) {
+ if ((z_timezone = zend_hash_str_find(myht, "timezone", sizeof("timezone")-1)) != NULL) {
convert_to_long(z_timezone_type);
- switch (Z_LVAL_P(z_timezone_type)) {
- case TIMELIB_ZONETYPE_OFFSET: {
- char *offset, *offset_start;
-
- offset = emalloc(sizeof(char) * (Z_STRLEN_P(z_timezone) + 1));
- memmove(offset, Z_STRVAL_P(z_timezone), Z_STRLEN_P(z_timezone)+1);
- offset_start = offset;
-
- ++offset;
- if(*offset_start == '+'){
- (*tzobj)->tzi.utc_offset = -1 * timelib_parse_tz_cor(&offset);
- } else {
- (*tzobj)->tzi.utc_offset = timelib_parse_tz_cor(&offset);
- }
- efree(offset_start);
- (*tzobj)->type = TIMELIB_ZONETYPE_OFFSET;
- (*tzobj)->initialized = 1;
- return SUCCESS;
- break;
- }
- case TIMELIB_ZONETYPE_ABBR:
- case TIMELIB_ZONETYPE_ID:
- if (SUCCESS == timezone_initialize(&tzi, Z_STRVAL_P(z_timezone) TSRMLS_CC)) {
- (*tzobj)->type = TIMELIB_ZONETYPE_ID;
- (*tzobj)->tzi.tz = tzi;
- (*tzobj)->initialized = 1;
- return SUCCESS;
- }
+ if (SUCCESS == timezone_initialize(*tzobj, Z_STRVAL_P(z_timezone) TSRMLS_CC)) {
+ return SUCCESS;
}
}
}
@@ -4942,7 +4952,6 @@ static zval *date_period_read_property(zval *object, zval *member, int type, zen
zv = std_object_handlers.read_property(object, member, type, cache_slot, rv TSRMLS_CC);
if (Z_TYPE_P(zv) == IS_OBJECT && Z_OBJ_HANDLER_P(zv, clone_obj)) {
/* defensive copy */
-//??? MAKE_STD_ZVAL(zv);
ZVAL_OBJ(zv, Z_OBJ_HANDLER_P(zv, clone_obj)(zv TSRMLS_CC));
}