Problem/Motivation

Much of the logic in system_time_zones() is outdated, as PHP now has the native ability to only return current timezones. While we're modernizing this logic, it makes sense to deprecate and remove (in Drupal 9) the old function.

Proposed resolution

Switch from using a regex to filter out old formats, and simply use \DateTimeZone::listIdentifiers(). At the same time, mark the old function deprecated and move this logic to Drupal\Core\Datetime\TimeZoneFormHelper::getOptionsList. Note, since this relies on Drupal\Core\StringTranslation\TranslatableMarkup, it can't go into a component such as DateTimePlus.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Issue fork drupal-3020455

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

jhedstrom created an issue. See original summary.

jhedstrom’s picture

Issue summary: View changes
jhedstrom’s picture

Status: Active » Needs review
Issue tags: +Needs change notice
StatusFileSize
new15.4 KB

Something like this. Note this is technically in the system module, but since it moves it to core's datetime, I'm leaving it under the datetime.module for visibility.

jhedstrom’s picture

Issue tags: +Kill includes, +OOP
alexpott’s picture

Status: Needs review » Needs work
  1. +++ b/core/lib/Drupal/Core/Datetime/DateHelper.php
    @@ -529,4 +529,48 @@ public static function dayOfWeekName($date = NULL, $abbr = TRUE) {
    +   * @param mixed $blank
    +   *   If evaluates true, prepend an empty time zone option to the array.
    ...
    +  public static function timeZones($blank = NULL, $grouped = FALSE) {
    

    Let's take the opportunity to make this the boolean that it is.

  2. +++ b/core/lib/Drupal/Core/Datetime/DateHelper.php
    @@ -529,4 +529,48 @@ public static function dayOfWeekName($date = NULL, $abbr = TRUE) {
    +    $zones = $blank ? ['' => t('- None selected -')] : [];
    ...
    +      $zones[$zone] = t('@zone', ['@zone' => t(str_replace('_', ' ', $zone))]);
    
    +++ b/core/tests/Drupal/Tests/Core/Datetime/DateHelperTest.php
    @@ -128,4 +128,62 @@ public function providerTestWeekDaysOrdered() {
    +if (!function_exists('t')) {
    +
    +  function t($string, array $args = []) {
    +    return strtr($string, $args);
    +  }
    

    Let's not use t() we can use TranslatableMarkup objects.

  3. +++ b/core/modules/system/system.module
    @@ -1262,8 +1263,15 @@ function system_mail($key, &$message, $params) {
     function system_time_zones($blank = NULL, $grouped = FALSE) {
    

    Let's call the new code here. So there are not two codebases. Also makes the lack of a deprecation test ok because we have no logic in this function then. It can cast the first param to a boolean.

alexpott’s picture

I think moving system_time_zones() to DateHelper seems a bit odd. The docs for that class are:

 * Defines Gregorian Calendar date values.
 *
 * Lots of helpful functions for use in massaging dates, specific to the
 * Gregorian calendar system. The values include both translated and
 * untranslated values.

This method doesn't fit into that. How about introducing a TimeZoneHelper?

+++ b/core/modules/system/system.module
@@ -1262,8 +1263,15 @@ function system_mail($key, &$message, $params) {
+ * @see https://www.drupal.org/node/3020455
...
+  @trigger_error('system_time_zones() is deprecated in Drupal 8.7.0 will be removed before Drupal 9.0.0. This function is no longer used in Drupal core. Use \Drupal\Core\Datetime\DateHelper::timeZones() instead. See https://www.drupal.org/node/3020455', E_USER_DEPRECATED);

This needs to be a change record not an issue node ID

jhedstrom’s picture

Status: Needs work » Needs review
StatusFileSize
new19.42 KB
new14.14 KB

Good finds! I think this addresses #5 and #6.

jhedstrom’s picture

StatusFileSize
new1.77 KB
new14.15 KB

Oops, I forgot to change some NULL values to booleans with the corresponding docblock change.

alexpott’s picture

Title: Deprecate system_time_zones() and move to DateHelper » Deprecate system_time_zones() and move to TimeZoneHelper
mpdonadio’s picture

Status: Needs review » Needs work
+++ b/core/lib/Drupal/Core/Datetime/TimeZoneHelper.php
@@ -0,0 +1,57 @@
+

Nit, extra space.

+++ b/core/modules/system/system.module
@@ -1262,42 +1263,16 @@ function system_mail($key, &$message, $params) {
-    if (preg_match('!^((Africa|America|Antarctica|Arctic|Asia|Atlantic|Australia|Europe|Indian|Pacific)/|UTC$)!', $zone)) {
-      $zones[$zone] = t('@zone', ['@zone' => t(str_replace('_', ' ', $zone))]);
-    }

It looks like the filtering is gone from TimeZoneHelper::getList() , and that this was essentially an unnecessary call since the goofy stuff is all in backzone now, and

+++ b/core/lib/Drupal/Core/Datetime/TimeZoneHelper.php
@@ -0,0 +1,57 @@
+   * Generate an array of time zones and their local time & date.

Since we are touch this, this comment is wrong. The function doesn't do anything with "their local time & date".

I'm wondering if is should read like

"Generate an array of time zones names.

This method retrieves the list of IANA time zones names that PHP is configured to use, for display to users. It does not return the backward compatible names (i.e., the ones defined in the backzone file)."

I'm also wondering if we should add a third parameter to allow people to get the ALL_BC list. This periodically comes up in issues.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

jhedstrom’s picture

Status: Needs work » Needs review
StatusFileSize
new2.45 KB
new14.87 KB

This should address #10 I think.

kim.pepper’s picture

Small nitpick:

+++ b/core/lib/Drupal/Core/Datetime/TimeZoneHelper.php
@@ -0,0 +1,63 @@
+   *   If TRUE, prepend an empty time zone option to the array.

Needs (optional) prefix.

kim.pepper’s picture

One more thing...

+++ b/core/modules/system/system.module
@@ -1266,42 +1267,16 @@ function system_mail($key, &$message, $params) {
+  @trigger_error('system_time_zones() is deprecated in Drupal 8.7.0 will be removed before Drupal 9.0.0. This function is no longer used in Drupal core. Use \Drupal\Core\Datetime\TimeZoneHelper::getList() instead. See https://www.drupal.org/node/3023528', E_USER_DEPRECATED);

Needs to be 8.8.0 and format as per https://www.drupal.org/project/coding_standards/issues/3024461

jhedstrom’s picture

StatusFileSize
new2 KB
new14.88 KB

This should address #13 and #14.

artis’s picture

Rather than adding a limited parameter only for ALL_BC, why not add $what = \DateTimeZone::ALL and $country = NULL as default parameters to the method so that any list that can be provided by \DateTimeZone::listIdentifiers() can be provided by this method?

kim.pepper’s picture

Having another look at this issue...

+++ b/core/lib/Drupal/Core/Datetime/TimeZoneHelper.php
@@ -0,0 +1,63 @@
+  public static function getList($blank = FALSE, $grouped = FALSE, $all_bc = FALSE) {

Not a big fan of boolean flags for DX. I'd prefer explicit wrapper methods like getGrouped() getWithBc() or something like that. Thoughts?

kim.pepper’s picture

Status: Needs review » Reviewed & tested by the community
StatusFileSize
new14.88 KB

Reconsidered my feedback in #17 and I think it's ok the way it is.

Marking as RTBC as this is a straight re-roll.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/lib/Drupal/Core/Datetime/TimeZoneHelper.php
    @@ -0,0 +1,63 @@
    +   * @param bool $blank
    +   *   (optional) If TRUE, prepend an empty time zone option to the array.
    ...
    +    $zones = $blank ? ['' => new TranslatableMarkup('- None selected -')] : [];
    
    +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampFormatter.php
    @@ -132,7 +133,7 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
    -      '#options' => ['' => $this->t('- Default site/user time zone -')] + system_time_zones(FALSE, TRUE),
    +      '#options' => ['' => $this->t('- Default site/user time zone -')] + TimeZoneHelper::getList(FALSE, TRUE),
    

    I wonder if we should consider ditching the $blank functionality here.

  2. +++ b/core/modules/system/system.module
    @@ -876,7 +877,7 @@ function system_user_timezone(&$form, FormStateInterface $form_state) {
    -    '#options' => system_time_zones($account->id() != $user->id(), TRUE),
    +    '#options' => TimeZoneHelper::getList($account->id() != $user->id(), TRUE),
    

    I guess this is the bit that makes it useful... still it feels odd to be putting form considerations in this list. But then again it only really exists for forms. I think this is more of a TimeZoneFormHelper than a generic helper.

  3. +++ b/core/lib/Drupal/Core/Datetime/TimeZoneHelper.php
    @@ -0,0 +1,63 @@
    +   * @param bool $all_bc
    +   *   (optional) Whether all timezones including backward compatible zones (
    +   *   \DateTimeZone::ALL_WITH_BC) should be returned.
    

    Why are we providing this option? It's not needed - and adds things to translate that never will be. I'm not convinced we should add this until necessary. The old function removed all of the BC timezones so not providing them is not a regression.

  4. +++ b/core/modules/user/src/Entity/User.php
    @@ -573,7 +574,7 @@ protected function getRoleStorage() {
    -    return array_keys(system_time_zones());
    +    return array_keys(TimeZoneHelper::getList());
    

    See this is weird because we creating a load of TranslatableMarkup for no reason. This could be return \DateTimeZone::listIdentifiers();. I think the docs for the helper needs to point out that all the keys are valid timezone identifiers provided by \DateTimeZone::listIdentifiers().

kim.pepper’s picture

Status: Needs work » Needs review
StatusFileSize
new14.35 KB
new13.17 KB
  1. Kept it for 2.
  2. Renamed to \Drupal\Core\Datetime\TimeZoneFormHelper::getOptionsList() which I think makes more sense
  3. Removed BC option, and removed test assertions
  4. Replaced with \DateTimeZone::listIdentifiers(). Couldn't find any other instances.
alexpott’s picture

  1. +++ b/core/modules/system/system.module
    @@ -1286,42 +1287,16 @@ function system_mail($key, &$message, $params) {
    + * @deprecated in Drupal 8.8.0 and will be removed from Drupal 9.0.0. This
    + *   function is no longer used in Drupal core.
    + *   Use \Drupal\Core\Datetime\TimeZoneHelper::getList() instead.
    ...
    +  @trigger_error('system_time_zones() is deprecated in Drupal 8.8.0. It will be removed from Drupal 9.0.0. This function is no longer used in Drupal core. Use \Drupal\Core\Datetime\TimeZoneHelper::getList() instead. See https://www.drupal.org/node/3023528', E_USER_DEPRECATED);
    

    or \DateTimeZone::listIdentifiers() instead - I think the CR should tell people to use the builtin when only using the machine value. Also need to update the class name.

  2. +++ b/core/modules/system/system.module
    @@ -1286,42 +1287,16 @@ function system_mail($key, &$message, $params) {
     function system_time_zones($blank = NULL, $grouped = FALSE) {
    

    Could do with a legacy test.

mpdonadio’s picture

Why are we providing this option? It's not needed - and adds things to translate that never will be. I'm not convinced we should add this until necessary. The old function removed all of the BC timezones so not providing them is not a regression.

The BC list is really for systems where an old name is baked into existing config from a time when it was a valid name. They are not supposed to be used human facing.

Other than a little polish, looks good.

alexpott’s picture

The BC list is really for systems where an old name is baked into existing config from a time when it was a valid name.

Yeah but

+++ b/core/modules/system/system.module
@@ -1286,42 +1287,16 @@ function system_mail($key, &$message, $params) {
-  $zonelist = timezone_identifiers_list();
-  $zones = $blank ? ['' => t('- None selected -')] : [];
-  foreach ($zonelist as $zone) {
-    // Because many time zones exist in PHP only for backward compatibility
-    // reasons and should not be used, the list is filtered by a regular
-    // expression.
-    if (preg_match('!^((Africa|America|Antarctica|Arctic|Asia|Atlantic|Australia|Europe|Indian|Pacific)/|UTC$)!', $zone)) {
-      $zones[$zone] = t('@zone', ['@zone' => t(str_replace('_', ' ', $zone))]);
-    }
-  }

This wasn't returning BC timezones anyway - right? So why do we need to add support for them? If you have them to deal with you need to write custom code atm - right?

alexpott’s picture

The preg_match() has been doing absolutely nothing since PHP5.3 :D - see https://3v4l.org/nYJ2R

mpdonadio’s picture

#23, sorry for not being clear. That was support your comment about not needing the BC flag. The backward/links discussion comes up every month or two on the TZ mailing list. The official docs more or less say don't use them directly anymore for new config: https://github.com/eggert/tz/blob/master/theory.html#L298 (search for "backward" not "backzone").

#24, yeah, did the same thing. I suspect I also checked this at #10 and there is a fiddle out there, lost for the ages.

kim.pepper’s picture

StatusFileSize
new15.29 KB
new2.2 KB

Re: #21

  1. Fixed
  2. Updated CR
kim.pepper’s picture

kim.pepper’s picture

Title: Deprecate system_time_zones() and move to TimeZoneHelper » Deprecate system_time_zones() and move to TimeZoneFormHelper

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

avpaderno’s picture

Issue tags: -Needs change notice +Needs change record
mpdonadio’s picture

Assigned: Unassigned » mpdonadio
Status: Needs review » Needs work
Issue tags: +Needs reroll

#26 doesn't apply to 8.9.x. Re-rolling.

mpdonadio’s picture

Assigned: mpdonadio » Unassigned
Status: Needs work » Needs review
Issue tags: -Needs reroll
StatusFileSize
new15.39 KB

Minor merge conflict in the use section.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mile23’s picture

Issue tags: +Needs reroll

Patch no longer applies.

Bhanu951 made their first commit to this issue’s fork.

Spokje made their first commit to this issue’s fork.

spokje’s picture

Assigned: Unassigned » spokje
Status: Needs review » Needs work

- Updated CR
- Rerolled latest patch in MR

bhanu951’s picture

@Spokje : Seems we were working simultaneously on this issue. Do Continue, I will pick another issue.

spokje’s picture

Thanks @Bhanu951, I wasn't aware you're working on it as well. Next time assign the issue to yourself, like I did, so I know somebody is already working on it.

spokje’s picture

Assigned: spokje » Unassigned
Status: Needs work » Needs review
Issue tags: -Needs change record, -Needs reroll
kim.pepper’s picture

RTBC+1 I worked on this issue too much to RTBC it myself.

spokje’s picture

Hiding old patch files to show that the MR is where the party is at.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs Review Queue Initiative, +Needs issue summary update

move this logic either to DateHelper.

This doesn't seem to be in the MR

Left a small nit picky thing in the MR too.

kim.pepper’s picture

Status: Needs work » Needs review

Rebased on 10.1.x

smustgrave’s picture

Status: Needs review » Needs work

Can the proposed solution be updated? Talks about moving to DateHelper but I don't see that?

kim.pepper’s picture

Issue summary: View changes
Status: Needs work » Needs review
Issue tags: -Needs issue summary update

Updated IS to refer to Drupal\Core\Datetime\TimeZoneFormHelper::getOptionsList

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Thank you with sticking with me on this one. Everything looks good to me.

  • catch committed efda42f2 on 10.1.x
    Issue #3020455 by Spokje, jhedstrom, kim.pepper, Bhanu951, mpdonadio,...
catch’s picture

Committed/pushed to 10.1.x, thanks! I'll open the follow-up and link it from here.

catch’s picture

Status: Reviewed & tested by the community » Fixed
catch’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

liquidcms’s picture

How is this list overridden?

With the old system_time_zones() function i hacked in a patch to add an alter (which i could then use to alter the list). I assumed if this was being redone the ability to alter the list would be included; but i don't see it here. Am i correct that this class can not be overridden?

kim.pepper’s picture

@liquidcms I suggest you create a new issue to add this feature.