Start/End times don't use the site's configured timezone

Created on 17 August 2023, over 1 year ago
Updated 16 November 2023, about 1 year ago

Problem/Motivation

When I save a new notification message with the start time the default time (the current time), it doesn't show. If I set the start time back the number of hours the timezone is ahead of UTC, then it shows.

Steps to reproduce

  1. Visit /admin/config/regional/settings
  2. Set timezone to "Los Angeles" (UTC-7) and Save
  3. Visit /admin/content/notification-message
  4. Create a new notification message
  5. Set it to show on all pages, or on
  6. The start time is the current time.
  7. Save it, and you won't see a message.
  8. Looking at the database, the time is stored in UTC as a VARCHAR(20). The time is correct; it's the UTC time of the local time I entered.
  9. Edit it, and set the start time 7 hours earlier.
  10. Save it, and you will see the message.

See this code:

  protected function loadMessages(): array {
        ...
        $date = $this->now(); /* This is in the site's configured timezone */
        $query = $storage->getQuery();
        $query->condition('publish_end_date', $date, '>='); /* The dates in the database are UTC */
        $query->condition('publish_start_date', $date, '<=');

And this:

  protected function now(): string {
    return (new DrupalDateTime())->format(
      DateTimeItemInterface::DATETIME_STORAGE_FORMAT
    );
  }

And this code from core's DrupalDateTime.php:

  /**
   * Overrides prepareTimezone().
   *
   * Override basic component timezone handling to use Drupal's
   * knowledge of the preferred user timezone.
   */
  protected function prepareTimezone($timezone) {
    if (empty($timezone)) {
      // Fallback to user or system default timezone.
      $timezone = date_default_timezone_get();
    }
    return parent::prepareTimezone($timezone);
  }

You can see that now() returns the localized time, but it's compared to UTC times stored in the database.

Proposed resolution

now() should use UTC timezone when constructing the current time. This works:

  protected function now(): string {
    return (new DrupalDateTime('now', 'UTC'))->format(
      DateTimeItemInterface::DATETIME_STORAGE_FORMAT
    );
  }

Remaining tasks

User interface changes

API changes

Data model changes

🐛 Bug report
Status

Fixed

Version

1.0

Component

Code

Created by

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Production build 0.71.5 2024