Make WordPress Core

Opened 2 years ago

Last modified 14 months ago

#53780 reopened defect (bug)

PHP 8.1: DateTimeZone::getTransitions() change

Reported by: autotutorial's profile autotutorial Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version:
Component: Date/Time Keywords: php81 close
Focuses: Cc:

Description

This is a follow-up to #49038.

PHP 8.1 getTransitions, The data format that the library uses has changed, and will now only contain a list of transitions up until the last time the *rules* changed.
https://bugs.php.net/bug.php?id=80963

Change History (11)

#1 @Rarst
2 years ago

From quick check we only use transition list in options for informational output about next upcoming transition for the chosen time zone.

So, assuming this lands in stable PHP release, we would need either alternate way to calculate next transition or drop this output.

#2 @swissspidy
2 years ago

  • Keywords php81 added
  • Summary changed from getTransitions change to PHP 8.1: DateTimeZone::getTransitions() change

#3 @GaryJ
15 months ago

  • Keywords close added

According the PHP bug report, this was fixed in 8.1.0beta3 / 8.1.0RC1, so can this be closed?

#4 @SergeyBiryukov
15 months ago

  • Milestone Awaiting Review deleted
  • Resolution set to reported-upstream
  • Status changed from new to closed

Yes, it looks like this was fixed in PHP 8.1.0beta3 and no further actions are needed for WordPress core at this time.

#5 @autotutorial
15 months ago

  • Resolution reported-upstream deleted
  • Status changed from closed to reopened
<?php
$tz = new DateTimeZone('America/Chicago');
$start = 1320562800;
$end = 1357020000;
$transitions = $tz->getTransitions($start, $end);
var_dump($transitions);
/*array(4) {
  [0]=>
  array(5) {
    ["ts"]=>
    int(1320562800)
    ["time"]=>
    string(24) "2011-11-06T07:00:00+0000"
    ["offset"]=>
    int(-21600)
    ["isdst"]=>
    bool(false)
    ["abbr"]=>
    string(3) "CST"
  }
  [1]=>
  array(5) {
    ["ts"]=>
    int(1320562800)
    ["time"]=>
    string(24) "2011-11-06T07:00:00+0000"
    ["offset"]=>
    int(-21600)
    ["isdst"]=>
    bool(false)
    ["abbr"]=>
    string(3) "CST"
  }
  [2]=>
  array(5) {
    ["ts"]=>
    int(1331452800)
    ["time"]=>
    string(24) "2012-03-11T08:00:00+0000"
    ["offset"]=>
    int(-18000)
    ["isdst"]=>
    bool(true)
    ["abbr"]=>
    string(3) "CDT"
  }
  [3]=>
  array(5) {
    ["ts"]=>
    int(1352012400)
    ["time"]=>
    string(24) "2012-11-04T07:00:00+0000"
    ["offset"]=>
    int(-21600)
    ["isdst"]=>
    bool(false)
    ["abbr"]=>
    string(3) "CST"
  }
}

PHP 8.1.0 - 8.1.5
array(1) {
  [0]=>
  array(5) {
    ["ts"]=>
    int(1320562800)
    ["time"]=>
    string(24) "2011-11-06T07:00:00+0000"
    ["offset"]=>
    int(-18000)
    ["isdst"]=>
    bool(true)
    ["abbr"]=>
    string(3) "CDT"
  }
}
*/

https://github.com/WordPress/WordPress/blob/master/wp-admin/options-general.php#L284

$transitions[1] ? :)

Last edited 15 months ago by autotutorial (previous) (diff)

#6 @SergeyBiryukov
15 months ago

  • Milestone set to Awaiting Review

#7 @Rarst
14 months ago

#55861 was marked as a duplicate.

#8 @Rarst
14 months ago

As of right now this should be fixed, starting with PHP 8.1.6. See https://3v4l.org/dT94b

It does look like future transitions weren't reported for PHP 8.1.0 to 8.1.5 inclusive.

I am not sure if that's anything we can do something about. Generally we are at mercy of PHP language providing timezone data to use.

We could not report DST detection, for PHP versions we know do not give us the data, but I don't think there is much precedent in core for such logic.

Last edited 14 months ago by Rarst (previous) (diff)

#9 @Rarst
14 months ago

I've tried to see if we can fish DST info out of DateTimeZone::listAbbreviations(), but the inconsistencies between PHP versions are even worse (and that's just for two time zones I tried) https://3v4l.org/qupTB#veol

#10 follow-up: @autotutorial
14 months ago

Actually you can check by creating a date with the DateTime class and php decides when DST or ST or other offset exists transition that does not use 3600 seconds, also we have (wordpress) never checked for coincidence if the timezone parameter is offset since the timezone is theoretically set to UTC by the WordPress core.
In this RFC change the preferred mode to php, but previously used a reverse default mode.

<?php

$tz = new DateTimeZone('Europe/Rome');
$date = new DateTime('now', $tz);
$dst = (bool) $date->format('I');
$transitions = $date->getTransitions($date->format('U'));
//$transitions is same transitions of $date?

https://github.com/WordPress/WordPress/blob/master/wp-settings.php#L68 and rfc php force DST https://wiki.php.net/rfc/datetime_and_daylight_saving_time

Or example 2 for one arg transitions and array > 1: https://3v4l.org/NiY8q

Last edited 14 months ago by autotutorial (previous) (diff)

#11 in reply to: ↑ 10 @Rarst
14 months ago

Replying to autotutorial:

Actually you can check by creating a date with the DateTime class and php decides when DST or ST or other offset exists

Checking if timezone is in DST right now doesn't help us to reimplement this. The current output is if time zone is changing to/from DST during a year, which is determined by checking for a future transition event.

Checking if time zone is or isn't in DST now doesn't tell that, because it might be permanent state of it. Some time zones don't have DST, some are permanently in DST. Or at least that's the real world situation, sans deep dive to check how PHP interprets that.

Maybe we should just drop the not having DST case altogether and rather not mention anything than risk incorrect and confusing info.

Note: See TracTickets for help on using tickets.