Fixed #7752, #8101, #81660: DateTimeZone::getTransitions() returns insufficient data

This commit is contained in:
Derick Rethans 2022-04-01 13:28:05 +01:00
parent 7d6a3af7db
commit e6c4988187
3 changed files with 102 additions and 20 deletions

6
NEWS
View File

@ -2,6 +2,12 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.1.6
- Date:
. Fixed bug GH-7752 (DateTimeZone::getTransitions() returns insufficient
data). (Derick)
. Fixed bug GH-8108 (Timezone doesn't work as intended). (Derick)
. Fixed bug #81660 (DateTimeZone::getTransitions() returns invalid data).
(Derick)
31 Mar 2022, PHP 8.1.5

View File

@ -3629,6 +3629,15 @@ PHP_FUNCTION(timezone_transitions_get)
add_assoc_string(&element, "abbr", &tzobj->tzi.tz->timezone_abbr[tzobj->tzi.tz->type[i].abbr_idx]); \
add_next_index_zval(return_value, &element);
#define add_from_tto(to,ts) \
array_init(&element); \
add_assoc_long(&element, "ts", ts); \
add_assoc_str(&element, "time", php_format_date(DATE_FORMAT_ISO8601, 13, ts, 0)); \
add_assoc_long(&element, "offset", (to)->offset); \
add_assoc_bool(&element, "isdst", (to)->is_dst); \
add_assoc_string(&element, "abbr", (to)->abbr); \
add_next_index_zval(return_value, &element);
#define add_last() add(tzobj->tzi.tz->bit64.timecnt - 1, timestamp_begin)
array_init(return_value);
@ -3658,7 +3667,13 @@ PHP_FUNCTION(timezone_transitions_get)
if (!found) {
if (tzobj->tzi.tz->bit64.timecnt > 0) {
add_last();
if (tzobj->tzi.tz->posix_info && tzobj->tzi.tz->posix_info->dst_end) {
timelib_time_offset *tto = timelib_get_time_zone_info(timestamp_begin, tzobj->tzi.tz);
add_from_tto(tto, timestamp_begin);
timelib_time_offset_dtor(tto);
} else {
add_last();
}
} else {
add_nominal();
}
@ -3671,31 +3686,34 @@ PHP_FUNCTION(timezone_transitions_get)
return;
}
}
if (tzobj->tzi.tz->posix_info && tzobj->tzi.tz->posix_info->dst_end) {
int i, j;
timelib_sll start_y, end_y, dummy_m, dummy_d;
timelib_sll last_transition_ts = tzobj->tzi.tz->trans[tzobj->tzi.tz->bit64.timecnt - 1];
}
if (tzobj->tzi.tz->posix_info && tzobj->tzi.tz->posix_info->dst_end) {
int i, j;
timelib_sll start_y, end_y, dummy_m, dummy_d;
timelib_sll last_transition_ts = tzobj->tzi.tz->trans[tzobj->tzi.tz->bit64.timecnt - 1];
/* Find out year for last transition */
timelib_unixtime2date(last_transition_ts, &start_y, &dummy_m, &dummy_d);
/* Find out year for last transition */
timelib_unixtime2date(last_transition_ts, &start_y, &dummy_m, &dummy_d);
/* Find out year for final boundary timestamp */
timelib_unixtime2date(timestamp_end, &end_y, &dummy_m, &dummy_d);
/* Find out year for final boundary timestamp */
timelib_unixtime2date(timestamp_end, &end_y, &dummy_m, &dummy_d);
for (i = start_y; i <= end_y; i++) {
timelib_posix_transitions transitions = { 0 };
for (i = start_y; i <= end_y; i++) {
timelib_posix_transitions transitions = { 0 };
timelib_get_transitions_for_year(tzobj->tzi.tz, i, &transitions);
timelib_get_transitions_for_year(tzobj->tzi.tz, i, &transitions);
for (j = 0; j < transitions.count; j++) {
if (transitions.times[j] <= last_transition_ts) {
continue;
}
if (transitions.times[j] > timestamp_end) {
return;
}
add_by_index(transitions.types[j], transitions.times[j]);
for (j = 0; j < transitions.count; j++) {
if (transitions.times[j] <= last_transition_ts) {
continue;
}
if (transitions.times[j] < timestamp_begin) {
continue;
}
if (transitions.times[j] > timestamp_end) {
return;
}
add_by_index(transitions.types[j], transitions.times[j]);
}
}
}

View File

@ -0,0 +1,58 @@
--TEST--
GH-7752: DateTimeZone::getTransitions() does not return enough information
--FILE--
<?php
function showTransitions(string $tzid, int $from)
{
$to = $from + ((2.5 * 366) * 24 * 60 * 60);
echo "{$tzid} from @{$from}-@{$to}:\n\n";
$tz = new DateTimeZone($tzid);
foreach ($tz->getTransitions($from, $to) as $t) {
printf("%12d %s %6d %s %s\n", $t['ts'], $t['time'], $t['offset'], $t['isdst'] ? "DST" : " x ", $t['abbr']);
}
echo "\n";
}
showTransitions('Europe/London', 1648342200);
showTransitions('America/Los_Angeles', 1648557596); // GH Issue 7752
showTransitions('America/Chicago', 1293861600); // PHP Bug 81660
showTransitions('Europe/Paris', 1645095600); // GH Issue 8108
?>
--EXPECT--
Europe/London from @1648342200-@1727398200:
1648342200 2022-03-27T00:50:00+0000 0 x GMT
1648342800 2022-03-27T01:00:00+0000 3600 DST BST
1667091600 2022-10-30T01:00:00+0000 0 x GMT
1679792400 2023-03-26T01:00:00+0000 3600 DST BST
1698541200 2023-10-29T01:00:00+0000 0 x GMT
1711846800 2024-03-31T01:00:00+0000 3600 DST BST
America/Los_Angeles from @1648557596-@1727613596:
1648557596 2022-03-29T12:39:56+0000 -25200 DST PDT
1667725200 2022-11-06T09:00:00+0000 -28800 x PST
1678615200 2023-03-12T10:00:00+0000 -25200 DST PDT
1699174800 2023-11-05T09:00:00+0000 -28800 x PST
1710064800 2024-03-10T10:00:00+0000 -25200 DST PDT
America/Chicago from @1293861600-@1372917600:
1293861600 2011-01-01T06:00:00+0000 -21600 x CST
1300003200 2011-03-13T08:00:00+0000 -18000 DST CDT
1320562800 2011-11-06T07:00:00+0000 -21600 x CST
1331452800 2012-03-11T08:00:00+0000 -18000 DST CDT
1352012400 2012-11-04T07:00:00+0000 -21600 x CST
1362902400 2013-03-10T08:00:00+0000 -18000 DST CDT
Europe/Paris from @1645095600-@1724151600:
1645095600 2022-02-17T11:00:00+0000 3600 x CET
1648342800 2022-03-27T01:00:00+0000 7200 DST CEST
1667091600 2022-10-30T01:00:00+0000 3600 x CET
1679792400 2023-03-26T01:00:00+0000 7200 DST CEST
1698541200 2023-10-29T01:00:00+0000 3600 x CET
1711846800 2024-03-31T01:00:00+0000 7200 DST CEST