From c9d63410bc03b06fbcad342da5aa4940d8149de2 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Thu, 6 Oct 2022 11:17:07 +0100
Subject: [PATCH] Issue #2993165 by kkasson, tatianag, Spokje, mpdonadio,
 xurizaemon, raman.b, wombatbuddy, pooja saraah, tannguyenhn, VladimirAus,
 ranjith_kumar_k_u, jannakha, pameeela: Date Only field shows incorrect
 default value when UTC date is different than user's date

---
 .../Field/FieldWidget/DateTimeWidgetBase.php  |   8 +-
 .../tests/src/Functional/DateTestBase.php     |   2 +
 .../src/Functional/DateTimeWidgetTest.php     | 102 ++++++++++++++++++
 3 files changed, 111 insertions(+), 1 deletion(-)
 create mode 100644 core/modules/datetime/tests/src/Functional/DateTimeWidgetTest.php

diff --git a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php
index aa7c959689b0..a5cbcece15f3 100644
--- a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php
+++ b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php
@@ -86,10 +86,16 @@ public function massageFormValues(array $values, array $form, FormStateInterface
   protected function createDefaultValue($date, $timezone) {
     // The date was created and verified during field_load(), so it is safe to
     // use without further inspection.
+    $year = $date->format('Y');
+    $month = $date->format('m');
+    $day = $date->format('d');
+    $date->setTimezone(new \DateTimeZone($timezone));
     if ($this->getFieldSetting('datetime_type') === DateTimeItem::DATETIME_TYPE_DATE) {
       $date->setDefaultDateTime();
+      // Reset the date to handle cases where the UTC offset is greater than
+      // 12 hours.
+      $date->setDate($year, $month, $day);
     }
-    $date->setTimezone(new \DateTimeZone($timezone));
     return $date;
   }
 
diff --git a/core/modules/datetime/tests/src/Functional/DateTestBase.php b/core/modules/datetime/tests/src/Functional/DateTestBase.php
index 60ca92bce6cb..57cc4cb641e1 100644
--- a/core/modules/datetime/tests/src/Functional/DateTestBase.php
+++ b/core/modules/datetime/tests/src/Functional/DateTestBase.php
@@ -99,6 +99,8 @@ protected function setUp(): void {
       'administer content types',
       'bypass node access',
       'administer node fields',
+      'administer node form display',
+      'administer node display',
     ]);
     $this->drupalLogin($web_user);
 
diff --git a/core/modules/datetime/tests/src/Functional/DateTimeWidgetTest.php b/core/modules/datetime/tests/src/Functional/DateTimeWidgetTest.php
new file mode 100644
index 000000000000..529d06c96b4d
--- /dev/null
+++ b/core/modules/datetime/tests/src/Functional/DateTimeWidgetTest.php
@@ -0,0 +1,102 @@
+<?php
+
+namespace Drupal\Tests\datetime\Functional;
+
+use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
+
+/**
+ * Tests Datetime widgets functionality.
+ *
+ * @group datetime
+ */
+class DateTimeWidgetTest extends DateTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * The default display settings to use for the formatters.
+   *
+   * @var array
+   */
+  protected $defaultSettings = ['timezone_override' => ''];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getTestFieldType() {
+    return 'datetime';
+  }
+
+  /**
+   * Test default value functionality.
+   */
+  public function testDateonlyDefaultValue() {
+    // Create a test content type.
+    $this->drupalCreateContentType(['type' => 'dateonly_content']);
+
+    // Create a field storage with settings to validate.
+    $field_storage = FieldStorageConfig::create([
+      'field_name' => 'field_dateonly',
+      'entity_type' => 'node',
+      'type' => 'datetime',
+      'settings' => ['datetime_type' => 'date'],
+    ]);
+    $field_storage->save();
+
+    $field = FieldConfig::create([
+      'field_storage' => $field_storage,
+      'bundle' => 'dateonly_content',
+    ]);
+    $field->save();
+
+    $edit = [
+      'fields[field_dateonly][region]' => 'content',
+      'fields[field_dateonly][type]' => 'datetime_default',
+    ];
+    $this->drupalGet('admin/structure/types/manage/dateonly_content/form-display');
+    $this->submitForm($edit, 'Save');
+    $this->drupalGet('admin/structure/types/manage/dateonly_content/display');
+    $this->submitForm($edit, 'Save');
+
+    // Set now as default_value.
+    $edit = [
+      'default_value_input[default_date_type]' => 'now',
+    ];
+    $this->drupalGet('admin/structure/types/manage/dateonly_content/fields/node.dateonly_content.field_dateonly');
+    $this->submitForm($edit, 'Save settings');
+
+    // Check that default value is selected in default value form.
+    $this->drupalGet('admin/structure/types/manage/dateonly_content/fields/node.dateonly_content.field_dateonly');
+    $option_field = $this->assertSession()->optionExists('edit-default-value-input-default-date-type', 'now');
+    $this->assertTrue($option_field->hasAttribute('selected'));
+    $this->assertSession()->fieldValueEquals('default_value_input[default_date]', '');
+
+    // Loop through defined timezones to test that date-only defaults work at
+    // the extremes.
+    foreach (static::$timezones as $timezone) {
+      $this->setSiteTimezone($timezone);
+      $this->assertEquals($timezone, $this->config('system.date')->get('timezone.default'), 'Time zone set to ' . $timezone);
+
+      $this->drupalGet('node/add/dateonly_content');
+
+      $request_time = $this->container->get('datetime.time')->getRequestTime();
+      $today = $this->dateFormatter->format($request_time, 'html_date', NULL, $timezone);
+      $this->assertSession()->fieldValueEquals('field_dateonly[0][value][date]', $today);
+
+      $edit = [
+        'title[0][value]' => $timezone,
+      ];
+      $this->submitForm($edit, 'Save');
+      $this->assertSession()->pageTextContains('dateonly_content ' . $timezone . ' has been created');
+
+      $node = $this->drupalGetNodeByTitle($timezone);
+      $today_storage = $this->dateFormatter->format($request_time, 'html_date', NULL, $timezone);
+      $this->assertEquals($today_storage, $node->field_dateonly->value);
+    }
+  }
+
+}
-- 
GitLab