Skip to content

Commit d676396

Browse files
committed
Implemented feature #45528: Allow the DateTimeZone constructor to accept timezones per offset too.
1 parent e196dce commit d676396

8 files changed

+57
-109
lines changed

ext/date/php_date.c

Lines changed: 40 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2297,7 +2297,7 @@ static zend_object_value date_object_clone_timezone(zval *this_ptr TSRMLS_DC)
22972297
case TIMELIB_ZONETYPE_ABBR:
22982298
new_obj->tzi.z.utc_offset = old_obj->tzi.z.utc_offset;
22992299
new_obj->tzi.z.dst = old_obj->tzi.z.dst;
2300-
new_obj->tzi.z.abbr = old_obj->tzi.z.abbr;
2300+
new_obj->tzi.z.abbr = strdup(old_obj->tzi.z.abbr);
23012301
break;
23022302
}
23032303

@@ -3238,6 +3238,26 @@ PHP_METHOD(DateTimeImmutable, sub)
32383238
}
32393239
/* }}} */
32403240

3241+
static void set_timezone_from_timelib_time(php_timezone_obj *tzobj, timelib_time *t)
3242+
{
3243+
tzobj->initialized = 1;
3244+
tzobj->type = t->zone_type;
3245+
switch (t->zone_type) {
3246+
case TIMELIB_ZONETYPE_ID:
3247+
tzobj->tzi.tz = t->tz_info;
3248+
break;
3249+
case TIMELIB_ZONETYPE_OFFSET:
3250+
tzobj->tzi.utc_offset = t->z;
3251+
break;
3252+
case TIMELIB_ZONETYPE_ABBR:
3253+
tzobj->tzi.z.utc_offset = t->z;
3254+
tzobj->tzi.z.dst = t->dst;
3255+
tzobj->tzi.z.abbr = strdup(t->tz_abbr);
3256+
break;
3257+
}
3258+
}
3259+
3260+
32413261
/* {{{ proto DateTimeZone date_timezone_get(DateTimeInterface object)
32423262
Return new DateTimeZone object relative to give DateTime
32433263
*/
@@ -3255,21 +3275,7 @@ PHP_FUNCTION(date_timezone_get)
32553275
if (dateobj->time->is_localtime/* && dateobj->time->tz_info*/) {
32563276
php_date_instantiate(date_ce_timezone, return_value TSRMLS_CC);
32573277
tzobj = (php_timezone_obj *) zend_object_store_get_object(return_value TSRMLS_CC);
3258-
tzobj->initialized = 1;
3259-
tzobj->type = dateobj->time->zone_type;
3260-
switch (dateobj->time->zone_type) {
3261-
case TIMELIB_ZONETYPE_ID:
3262-
tzobj->tzi.tz = dateobj->time->tz_info;
3263-
break;
3264-
case TIMELIB_ZONETYPE_OFFSET:
3265-
tzobj->tzi.utc_offset = dateobj->time->z;
3266-
break;
3267-
case TIMELIB_ZONETYPE_ABBR:
3268-
tzobj->tzi.z.utc_offset = dateobj->time->z;
3269-
tzobj->tzi.z.dst = dateobj->time->dst;
3270-
tzobj->tzi.z.abbr = strdup(dateobj->time->tz_abbr);
3271-
break;
3272-
}
3278+
set_timezone_from_timelib_time(tzobj, dateobj->time);
32733279
} else {
32743280
RETURN_FALSE;
32753281
}
@@ -3620,23 +3626,21 @@ PHP_FUNCTION(date_diff)
36203626
}
36213627
/* }}} */
36223628

3623-
static int timezone_initialize(timelib_tzinfo **tzi, /*const*/ char *tz TSRMLS_DC)
3629+
static int timezone_initialize(php_timezone_obj *tzobj, /*const*/ char *tz TSRMLS_DC)
36243630
{
3625-
char *tzid;
3626-
3627-
*tzi = NULL;
3628-
3629-
if ((tzid = timelib_timezone_id_from_abbr(tz, -1, 0))) {
3630-
*tzi = php_date_parse_tzfile(tzid, DATE_TIMEZONEDB TSRMLS_CC);
3631+
timelib_time *dummy_t = ecalloc(1, sizeof(timelib_time));
3632+
int dst, not_found;
3633+
char *orig_tz = tz;
3634+
3635+
dummy_t->z = timelib_parse_zone(&tz, &dst, dummy_t, &not_found, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
3636+
if (not_found) {
3637+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad timezone (%s)", orig_tz);
3638+
efree(dummy_t);
3639+
return FAILURE;
36313640
} else {
3632-
*tzi = php_date_parse_tzfile(tz, DATE_TIMEZONEDB TSRMLS_CC);
3633-
}
3634-
3635-
if (*tzi) {
3641+
set_timezone_from_timelib_time(tzobj, dummy_t TSRMLS_CC);
3642+
efree(dummy_t);
36363643
return SUCCESS;
3637-
} else {
3638-
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad timezone (%s)", tz);
3639-
return FAILURE;
36403644
}
36413645
}
36423646

@@ -3647,19 +3651,15 @@ PHP_FUNCTION(timezone_open)
36473651
{
36483652
char *tz;
36493653
int tz_len;
3650-
timelib_tzinfo *tzi = NULL;
36513654
php_timezone_obj *tzobj;
36523655

36533656
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &tz, &tz_len) == FAILURE) {
36543657
RETURN_FALSE;
36553658
}
3656-
if (SUCCESS != timezone_initialize(&tzi, tz TSRMLS_CC)) {
3659+
tzobj = zend_object_store_get_object(php_date_instantiate(date_ce_timezone, return_value TSRMLS_CC) TSRMLS_CC);
3660+
if (SUCCESS != timezone_initialize(tzobj, tz TSRMLS_CC)) {
36573661
RETURN_FALSE;
36583662
}
3659-
tzobj = zend_object_store_get_object(php_date_instantiate(date_ce_timezone, return_value TSRMLS_CC) TSRMLS_CC);
3660-
tzobj->type = TIMELIB_ZONETYPE_ID;
3661-
tzobj->tzi.tz = tzi;
3662-
tzobj->initialized = 1;
36633663
}
36643664
/* }}} */
36653665

@@ -3670,18 +3670,13 @@ PHP_METHOD(DateTimeZone, __construct)
36703670
{
36713671
char *tz;
36723672
int tz_len;
3673-
timelib_tzinfo *tzi = NULL;
36743673
php_timezone_obj *tzobj;
36753674
zend_error_handling error_handling;
36763675

36773676
zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
36783677
if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &tz, &tz_len)) {
3679-
if (SUCCESS == timezone_initialize(&tzi, tz TSRMLS_CC)) {
3680-
tzobj = zend_object_store_get_object(getThis() TSRMLS_CC);
3681-
tzobj->type = TIMELIB_ZONETYPE_ID;
3682-
tzobj->tzi.tz = tzi;
3683-
tzobj->initialized = 1;
3684-
} else {
3678+
tzobj = zend_object_store_get_object(getThis() TSRMLS_CC);
3679+
if (FAILURE == timezone_initialize(tzobj, tz TSRMLS_CC)) {
36853680
ZVAL_NULL(getThis());
36863681
}
36873682
}
@@ -3693,39 +3688,12 @@ static int php_date_timezone_initialize_from_hash(zval **return_value, php_timez
36933688
{
36943689
zval **z_timezone = NULL;
36953690
zval **z_timezone_type = NULL;
3696-
timelib_tzinfo *tzi;
36973691

36983692
if (zend_hash_find(myht, "timezone_type", 14, (void**) &z_timezone_type) == SUCCESS) {
36993693
if (zend_hash_find(myht, "timezone", 9, (void**) &z_timezone) == SUCCESS) {
37003694
convert_to_long(*z_timezone_type);
3701-
switch (Z_LVAL_PP(z_timezone_type)) {
3702-
case TIMELIB_ZONETYPE_OFFSET: {
3703-
char *offset, *offset_start;
3704-
3705-
offset = emalloc(sizeof(char) * (Z_STRLEN_PP(z_timezone) + 1));
3706-
memmove(offset, Z_STRVAL_PP(z_timezone), Z_STRLEN_PP(z_timezone)+1);
3707-
offset_start = offset;
3708-
3709-
++offset;
3710-
if(*offset_start == '+'){
3711-
(*tzobj)->tzi.utc_offset = -1 * timelib_parse_tz_cor(&offset);
3712-
} else {
3713-
(*tzobj)->tzi.utc_offset = timelib_parse_tz_cor(&offset);
3714-
}
3715-
efree(offset_start);
3716-
(*tzobj)->type = TIMELIB_ZONETYPE_OFFSET;
3717-
(*tzobj)->initialized = 1;
3718-
return SUCCESS;
3719-
break;
3720-
}
3721-
case TIMELIB_ZONETYPE_ABBR:
3722-
case TIMELIB_ZONETYPE_ID:
3723-
if (SUCCESS == timezone_initialize(&tzi, Z_STRVAL_PP(z_timezone) TSRMLS_CC)) {
3724-
(*tzobj)->type = TIMELIB_ZONETYPE_ID;
3725-
(*tzobj)->tzi.tz = tzi;
3726-
(*tzobj)->initialized = 1;
3727-
return SUCCESS;
3728-
}
3695+
if (SUCCESS == timezone_initialize(*tzobj, Z_STRVAL_PP(z_timezone) TSRMLS_CC)) {
3696+
return SUCCESS;
37293697
}
37303698
}
37313699
}

ext/date/tests/DateTimeZone_clone_basic1.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ if ($clone != $orig) {
3131
*** Testing clone on DateTime objects ***
3232
object(DateTimeZone)#%d (2) {
3333
["timezone_type"]=>
34-
int(3)
34+
int(2)
3535
["timezone"]=>
36-
string(3) "UTC"
36+
string(3) "GMT"
3737
}
3838
object(DateTimeZone)#%d (2) {
3939
["timezone_type"]=>
40-
int(3)
40+
int(2)
4141
["timezone"]=>
42-
string(3) "UTC"
42+
string(3) "GMT"
4343
}
4444
TEST PASSED : Objects equal but not indetical
4545
===DONE===

ext/date/tests/DateTimeZone_construct_basic.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ var_dump( new DateTimeZone("America/Los_Angeles") );
2323
*** Testing new DateTimeZone() : basic functionality ***
2424
object(DateTimeZone)#%d (2) {
2525
["timezone_type"]=>
26-
int(3)
26+
int(2)
2727
["timezone"]=>
28-
string(3) "UTC"
28+
string(3) "GMT"
2929
}
3030
object(DateTimeZone)#%d (2) {
3131
["timezone_type"]=>

ext/date/tests/DateTimeZone_construct_variation1.phpt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,9 @@ $inputs = array(
4848
'int 0' => 0,
4949
'int 1' => 1,
5050
'int 12345' => 12345,
51-
'int -12345' => -12345,
5251

5352
// float data
5453
'float 10.5' => 10.5,
55-
'float -10.5' => -10.5,
5654
'float .5' => .5,
5755

5856
// array data
@@ -123,15 +121,9 @@ FAILED: DateTimeZone::__construct(): Unknown or bad timezone (1)
123121
-- int 12345 --
124122
FAILED: DateTimeZone::__construct(): Unknown or bad timezone (12345)
125123

126-
-- int -12345 --
127-
FAILED: DateTimeZone::__construct(): Unknown or bad timezone (-12345)
128-
129124
-- float 10.5 --
130125
FAILED: DateTimeZone::__construct(): Unknown or bad timezone (10.5)
131126

132-
-- float -10.5 --
133-
FAILED: DateTimeZone::__construct(): Unknown or bad timezone (-10.5)
134-
135127
-- float .5 --
136128
FAILED: DateTimeZone::__construct(): Unknown or bad timezone (0.5)
137129

ext/date/tests/DateTimeZone_serialize_type_2.phpt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@ var_dump( $tz2->getName() );
2020
--EXPECTF--
2121
object(DateTimeZone)#%d (2) {
2222
["timezone_type"]=>
23-
int(3)
23+
int(2)
2424
["timezone"]=>
25-
string(16) "America/New_York"
25+
string(3) "EST"
2626
}
27-
string(88) "O:12:"DateTimeZone":2:{s:13:"timezone_type";i:3;s:8:"timezone";s:16:"America/New_York";}"
27+
string(74) "O:12:"DateTimeZone":2:{s:13:"timezone_type";i:2;s:8:"timezone";s:3:"EST";}"
2828
object(DateTimeZone)#%d (2) {
2929
["timezone_type"]=>
30-
int(3)
30+
int(2)
3131
["timezone"]=>
32-
string(16) "America/New_York"
32+
string(3) "EST"
3333
}
34-
string(16) "America/New_York"
34+
string(3) "EST"
3535
===DONE===

ext/date/tests/DateTimeZone_serialize_type_3.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ var_dump( $tz2->getName() );
1818
?>
1919
===DONE===
2020
--EXPECTF--
21-
object(DateTimeZone)#%d (2) {
21+
object(DateTimeZone)#1 (2) {
2222
["timezone_type"]=>
2323
int(3)
2424
["timezone"]=>
2525
string(16) "America/New_York"
2626
}
2727
string(88) "O:12:"DateTimeZone":2:{s:13:"timezone_type";i:3;s:8:"timezone";s:16:"America/New_York";}"
28-
object(DateTimeZone)#%d (2) {
28+
object(DateTimeZone)#2 (2) {
2929
["timezone_type"]=>
3030
int(3)
3131
["timezone"]=>

ext/date/tests/timezone_open_basic1.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ var_dump( timezone_open("America/Los_Angeles") );
2020
*** Testing timezone_open() : basic functionality ***
2121
object(DateTimeZone)#%d (2) {
2222
["timezone_type"]=>
23-
int(3)
23+
int(2)
2424
["timezone"]=>
25-
string(3) "UTC"
25+
string(3) "GMT"
2626
}
2727
object(DateTimeZone)#%d (2) {
2828
["timezone_type"]=>
@@ -36,4 +36,4 @@ object(DateTimeZone)#%d (2) {
3636
["timezone"]=>
3737
string(19) "America/Los_Angeles"
3838
}
39-
===DONE===
39+
===DONE===

ext/date/tests/timezone_open_variation1.phpt

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,9 @@ $inputs = array(
4848
'int 0' => 0,
4949
'int 1' => 1,
5050
'int 12345' => 12345,
51-
'int -12345' => -12345,
5251

5352
// float data
5453
'float 10.5' => 10.5,
55-
'float -10.5' => -10.5,
5654
'float .5' => .5,
5755

5856
// array data
@@ -124,21 +122,11 @@ bool(false)
124122
Warning: timezone_open(): Unknown or bad timezone (12345) in %s on line %d
125123
bool(false)
126124

127-
-- int -12345 --
128-
129-
Warning: timezone_open(): Unknown or bad timezone (-12345) in %s on line %d
130-
bool(false)
131-
132125
-- float 10.5 --
133126

134127
Warning: timezone_open(): Unknown or bad timezone (10.5) in %s on line %d
135128
bool(false)
136129

137-
-- float -10.5 --
138-
139-
Warning: timezone_open(): Unknown or bad timezone (-10.5) in %s on line %d
140-
bool(false)
141-
142130
-- float .5 --
143131

144132
Warning: timezone_open(): Unknown or bad timezone (0.5) in %s on line %d

0 commit comments

Comments
 (0)