Skip to content

Fix GH-#18051 (DateTimeZone->getTransitions can return first transition twice) #18054

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

marc-mabe
Copy link
Contributor

This PR fixes duplicated transitions in DateTimeZone->getTransitions() by memorizing the last transition timestamp reported before the next transition gets added to the resulting array.

Copy link
Member

@derickr derickr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but with a comment to address first.

add_assoc_bool(&element, "isdst", tzobj->tzi.tz->type[i].isdst); \
add_assoc_string(&element, "abbr", &tzobj->tzi.tz->timezone_abbr[tzobj->tzi.tz->type[i].abbr_idx]); \
add_next_index_zval(return_value, &element);
if (timestamp_added_last != ts) { \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DItto

@marc-mabe marc-mabe force-pushed the fix/DateTimeZone-getTransitions-gh18051 branch from c3df98b to 18350af Compare March 31, 2025 07:19
@marc-mabe
Copy link
Contributor Author

@derickr It turns out that the transitions are not sequential in all cases - at least not on 32bit.
On digging deeper into the failed test case of bug 80963 I get the following on master:

var_dump(array_slice(new DateTimeZone("America/New_York")->getTransitions(), 0, 3));
array(3) {
  [0]=>
  array(5) {
    ["ts"]=>
    int(-2147483648)
    ["time"]=>
    string(25) "1901-12-13T20:45:52+00:00"
    ["offset"]=>
    int(-17762)
    ["isdst"]=>
    bool(false)
    ["abbr"]=>
    string(3) "LMT"
  }
  [1]=>
  array(5) {
    ["ts"]=>
    int(1577316496)
    ["time"]=>
    string(25) "2019-12-25T23:28:16+00:00"
    ["offset"]=>
    int(-18000)
    ["isdst"]=>
    bool(false)
    ["abbr"]=>
    string(3) "EST"
  }
  [2]=>
  array(5) {
    ["ts"]=>
    int(-1633280400)
    ["time"]=>
    string(25) "1918-03-31T07:00:00+00:00"
    ["offset"]=>
    int(-14400)
    ["isdst"]=>
    bool(true)
    ["abbr"]=>
    string(3) "EDT"
  }
}

@marc-mabe
Copy link
Contributor Author

@derickr Using a different approach now to avoid one variable and some assignments / comparisons.
It also fixes an integer overflow on 32bit at if (tzobj->tzi.tz->trans[i] < timestamp_end) { add(i, tzobj->tzi.tz->trans[i]); } and updated the test for bug 80963.

@derickr
Copy link
Member

derickr commented Apr 10, 2025

They should definitely be sequential. Something else odd is going on here.

@marc-mabe marc-mabe force-pushed the fix/DateTimeZone-getTransitions-gh18051 branch from 7e136cf to e9ed392 Compare May 13, 2025 09:33
@marc-mabe marc-mabe force-pushed the fix/DateTimeZone-getTransitions-gh18051 branch from e9ed392 to cc1c5a0 Compare May 13, 2025 09:34
@marc-mabe
Copy link
Contributor Author

marc-mabe commented May 13, 2025

@derickr

They should definitely be sequential. Something else odd is going on here.

OK, they are sequential, but the transitions are all int64 and the second transition of America/New_York is at -2717650800 (1883-11-18T17:00:00+00:00) which overflows on int32 to 1577316495 (2019-12-25T23:28:16+00:00).

The changes in this PR are fixing this issue as well.

Here is what is happening on America/New_York

64 bit 32 bit before 32 bit after
add_nominal (-9223372036854775808 LMT) add_nominal (-2147483648 LMT) add_nominal (-2147483648 LMT)
add (-2717650800 EST) add (-2717650800 overflow to 1577316496 EST) upd_prev (-2147483648 EST)
add (-1633280400 EDT) add (-1633280400 EDT) add (-1633280400 EDT)
... ... ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants