diff --git a/core/modules/datetime/config/schema/datetime.schema.yml b/core/modules/datetime/config/schema/datetime.schema.yml index 406a2fd..46a52c7 100644 --- a/core/modules/datetime/config/schema/datetime.schema.yml +++ b/core/modules/datetime/config/schema/datetime.schema.yml @@ -7,6 +7,9 @@ field.storage_settings.datetime: datetime_type: type: string label: 'Date type' + timezone_handling: + type: string + label: 'Timezone handling' field.field_settings.datetime: type: mapping diff --git a/core/modules/datetime/src/Plugin/Field/FieldType/DateTimeItem.php b/core/modules/datetime/src/Plugin/Field/FieldType/DateTimeItem.php index a7dd1c3..404cef0 100644 --- a/core/modules/datetime/src/Plugin/Field/FieldType/DateTimeItem.php +++ b/core/modules/datetime/src/Plugin/Field/FieldType/DateTimeItem.php @@ -33,6 +33,7 @@ class DateTimeItem extends FieldItemBase { public static function defaultStorageSettings() { return array( 'datetime_type' => 'datetime', + 'timezone_handling' => 'site', ) + parent::defaultStorageSettings(); } @@ -61,6 +62,10 @@ public static function propertyDefinitions(FieldStorageDefinitionInterface $fiel ->setClass('\Drupal\datetime\DateTimeComputed') ->setSetting('date source', 'value'); + // @todo Shouldn't this only be needed if `$field_definition->getSetting('timezone_handling') === TRUE`? + $properties['timezone'] = DataDefinition::create('string') + ->setLabel(t('Timezone')); + return $properties; } @@ -68,7 +73,7 @@ public static function propertyDefinitions(FieldStorageDefinitionInterface $fiel * {@inheritdoc} */ public static function schema(FieldStorageDefinitionInterface $field_definition) { - return array( + $schema = array( 'columns' => array( 'value' => array( 'description' => 'The date value.', @@ -80,6 +85,17 @@ public static function schema(FieldStorageDefinitionInterface $field_definition) 'value' => array('value'), ), ); + + // Store the timezone if timezone handling is per-date. + if ($field_definition->getSetting('timezone_handling') === 'date') { + $schema['columns']['timezone'] = array( + 'description' => 'The date timezone', + 'type' => 'varchar', + 'length' => 50, + ); + } + + return $schema; } /** @@ -99,6 +115,20 @@ public function storageSettingsForm(array &$form, FormStateInterface $form_state ), ); + $element['timezone_handling'] = array( + '#type' => 'select', + '#title' => t('Timezone handling'), + '#options' => array( + 'site' => t("Site's timezone"), + 'date' => t("Date's timezone"), + 'user' => t("User's timezone"), + 'utc' => 'UTC', + 'none' => t('No timezone conversion'), + ), + '#default_value' => $this->getSetting('timezone_handling'), + '#required' => TRUE, + ); + return $element; } diff --git a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php index dfe750e..8c3dcee 100644 --- a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php +++ b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php @@ -39,6 +39,15 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen '#required' => $element['#required'], ); + if ($this->getFieldSetting('timezone_handling') === 'date') { + $element['timezone'] = array( + '#type' => 'select', + '#options' => \DateTimeZone::listIdentifiers(), + // Default to user's timezone. + '#default_value' => drupal_get_user_timezone(), + ); + } + if ($items[$delta]->date) { $date = $items[$delta]->date; // The date was created and verified during field_load(), so it is safe to diff --git a/core/modules/datetime/src/Tests/DateTimeItemTest.php b/core/modules/datetime/src/Tests/DateTimeItemTest.php index d83d2a2..0771103 100644 --- a/core/modules/datetime/src/Tests/DateTimeItemTest.php +++ b/core/modules/datetime/src/Tests/DateTimeItemTest.php @@ -9,6 +9,8 @@ use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FieldItemInterface; +use Drupal\entity_test\Entity\EntityTest; +use Drupal\field\Entity\FieldStorageConfig; use Drupal\field\Tests\FieldUnitTestBase; /** @@ -33,7 +35,10 @@ protected function setUp() { 'field_name' => 'field_datetime', 'type' => 'datetime', 'entity_type' => 'entity_test', - 'settings' => array('datetime_type' => 'date'), + 'settings' => array( + 'datetime_type' => 'date', + 'timezone_handling' => 'site', + ), )); $field_storage->save(); $field = entity_create('field_config', array( @@ -122,4 +127,28 @@ public function testSetValueProperty() { $this->assertEqual($entity->field_datetime[0]->value, $value, '"Value" property can be set directly.'); } + /** + * Tests DateTimeItem with per-date timezone handling. + */ + public function testTimezoneDate() { + /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */ + $field_storage = FieldStorageConfig::load('entity_test.field_datetime'); + $field_storage->setSetting('timezone_handling', 'date'); + $field_storage->save(); + + // Use a non-UTC timezone. + $timezone = 'America/Yellowknife'; + + $entity = EntityTest::create(); + $value = '2014-01-01T20:00:00Z'; + + $entity->set('field_datetime', ['value' => $value, 'timezone' => $timezone]); + $entity->save(); + + // Load the entity. + $id = $entity->id(); + $entity = EntityTest::load($id); + $this->assertEqual($timezone, $entity->field_datetime[0]->timezone, '"timezone" property can be set.'); + } + }