diff --git a/core/modules/datetime_range/config/schema/datetime_range.schema.yml b/core/modules/datetime_range/config/schema/datetime_range.schema.yml
index f4765d37d5..92a5bde733 100644
--- a/core/modules/datetime_range/config/schema/datetime_range.schema.yml
+++ b/core/modules/datetime_range/config/schema/datetime_range.schema.yml
@@ -6,6 +6,9 @@ field.storage_settings.daterange:
   type: field.storage_settings.datetime
   label: 'Date range settings'
   mapping:
+    optional_start_date:
+      type: boolean
+      label: 'Optional start date'
     optional_end_date:
       type: boolean
       label: 'Optional end date'
diff --git a/core/modules/datetime_range/datetime_range.install b/core/modules/datetime_range/datetime_range.install
index 074d1cd9a5..e3c26ae537 100644
--- a/core/modules/datetime_range/datetime_range.install
+++ b/core/modules/datetime_range/datetime_range.install
@@ -19,6 +19,12 @@ function datetime_range_update_8900() {
     $schema_key = $config->getTargetEntityTypeId() . '.field_schema_data.' . $config->getName();
     $tables = $storage_schema->get($schema_key);
 
+    $field_name = $config->getName() . '_value';
+    foreach ($tables as $table_name => &$table) {
+      $table['fields'][$field_name]['not null'] = FALSE;
+      $database_schema->changeField($table_name, $field_name, $field_name, $table['fields'][$field_name]);
+    }
+
     $field_name = $config->getName() . '_end_value';
     foreach ($tables as $table_name => &$table) {
       $table['fields'][$field_name]['not null'] = FALSE;
diff --git a/core/modules/datetime_range/src/DateTimeRangeTrait.php b/core/modules/datetime_range/src/DateTimeRangeTrait.php
index 806e93ff98..16225e7e17 100644
--- a/core/modules/datetime_range/src/DateTimeRangeTrait.php
+++ b/core/modules/datetime_range/src/DateTimeRangeTrait.php
@@ -17,12 +17,11 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
     $separator = $this->getSetting('separator');
 
     foreach ($items as $delta => $item) {
-      if (!empty($item->start_date)) {
-        /** @var \Drupal\Core\Datetime\DrupalDateTime $start_date */
-        $start_date = $item->start_date;
-        /** @var \Drupal\Core\Datetime\DrupalDateTime $end_date */
-        $end_date = $item->end_date;
-
+      /** @var \Drupal\Core\Datetime\DrupalDateTime $start_date */
+      $start_date = $item->start_date;
+      /** @var \Drupal\Core\Datetime\DrupalDateTime $end_date */
+      $end_date = $item->end_date;
+      if (!empty($start_date)) {
         if ($end_date !== NULL && $start_date->getTimestamp() !== $end_date->getTimestamp()) {
           $elements[$delta] = [
             'start_date' => $this->buildDateWithIsoAttribute($start_date),
@@ -41,6 +40,11 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
           }
         }
       }
+      if (empty($start_date) && !empty($end_date)) {
+        $elements[$delta] = [
+          'end_date' => $this->buildDateWithIsoAttribute($end_date),
+        ];
+      }
     }
 
     return $elements;
diff --git a/core/modules/datetime_range/src/Plugin/Field/FieldType/DateRangeItem.php b/core/modules/datetime_range/src/Plugin/Field/FieldType/DateRangeItem.php
index 9aeca189a4..e0622cb0f4 100644
--- a/core/modules/datetime_range/src/Plugin/Field/FieldType/DateRangeItem.php
+++ b/core/modules/datetime_range/src/Plugin/Field/FieldType/DateRangeItem.php
@@ -127,11 +127,24 @@ public static function generateSampleValue(FieldDefinitionInterface $field_defin
    */
   public function isEmpty() {
     $start_value = $this->get('value')->getValue();
+    // 4. not start optional && not end optional
+    $end_value = $this->get('end_value')->getValue();
+
+    $field_definition = $this->getFieldDefinition()->getFieldStorageDefinition();
+    // 2. start optional && not end optional
+    if ($field_definition->getSetting('optional_start_date')) {
+      return $end_value === NULL || $end_value === '';
+    }
+
+    // 1. start optional && end optional,
+    if ($field_definition->getSetting('optional_start_date') && $field_definition->getSetting('optional_end_date')) {
+      return FALSE;
+    }
+    // 3. not start optional && end optional
     if ($this->getFieldDefinition()->getFieldStorageDefinition()->getSetting('optional_end_date')) {
       return $start_value === NULL || $start_value === '';
     }
 
-    $end_value = $this->get('end_value')->getValue();
     return ($start_value === NULL || $start_value === '') && ($end_value === NULL || $end_value === '');
   }
 
diff --git a/core/modules/datetime_range/src/Plugin/Field/FieldWidget/DateRangeWidgetBase.php b/core/modules/datetime_range/src/Plugin/Field/FieldWidget/DateRangeWidgetBase.php
index 09bcc80d15..0eea938930 100644
--- a/core/modules/datetime_range/src/Plugin/Field/FieldWidget/DateRangeWidgetBase.php
+++ b/core/modules/datetime_range/src/Plugin/Field/FieldWidget/DateRangeWidgetBase.php
@@ -19,18 +19,23 @@ class DateRangeWidgetBase extends DateTimeWidgetBase {
    */
   public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
     $element = parent::formElement($items, $delta, $element, $form, $form_state);
+    $optional_start_date = $this->getFieldSetting('optional_start_date');
     $optional_end_date = $this->getFieldSetting('optional_end_date');
 
     // Wrap all of the select elements with a fieldset.
     $element['#theme_wrappers'][] = 'fieldset';
 
     $element['#element_validate'][] = [$this, 'validateStartEnd'];
-    $element['value']['#title'] = $this->t('Start date');
+    $element['value']['#title'] = $optional_start_date ? $this->t('Start date (optional)') : $this->t('Start date');
 
     $element['end_value'] = [
       '#title' => $optional_end_date ? $this->t('End date (optional)') : $this->t('End date'),
     ] + $element['value'];
 
+    if ($element['#required'] && $optional_start_date) {
+      $element['value']['#required'] = FALSE;
+    }
+
     if ($element['#required'] && $optional_end_date) {
       $element['end_value']['#required'] = FALSE;
     }
diff --git a/core/modules/datetime_range/tests/src/Kernel/DateRangeItemTest.php b/core/modules/datetime_range/tests/src/Kernel/DateRangeItemTest.php
index dd0fe93c6b..f8d7c5220e 100644
--- a/core/modules/datetime_range/tests/src/Kernel/DateRangeItemTest.php
+++ b/core/modules/datetime_range/tests/src/Kernel/DateRangeItemTest.php
@@ -103,6 +103,43 @@ public function testDateOnly() {
     $this->assertEquals('12:00:00', $end_date->format('H:i:s'));
   }
 
+  /**
+   * Test optional start date.
+   */
+  public function testOptionalStartDate() {
+    $field_name = $this->fieldStorage->getName();
+
+    $this->fieldStorage->setSettings([
+      'datetime_type' => DateRangeItem::DATETIME_TYPE_DATE,
+      'optional_start_date' => FALSE,
+    ])
+      ->save();
+
+    $value = [
+      'value' => NULL,
+      'end_value' => '2016-09-21',
+    ];
+
+    // Verify entity without optional_end_date enabled.
+    $entity = EntityTest::create([
+      'name' => $this->randomString(),
+      $field_name => $value,
+    ]);
+    $this->assertNotEqual(count($entity->validate()), 0);
+
+    // Verify entity with the optional_start_date enabled.
+    $this->fieldStorage->setSetting('optional_start_date', TRUE)
+      ->save();
+    $entity = EntityTest::create([
+      'name' => $this->randomString(),
+      $field_name => $value,
+    ]);
+    $this->entityValidateAndSave($entity);
+
+    // Verify changing the date value.
+    $this->assertEqual($entity->{$field_name}->value, $value['value']);
+  }
+
   /**
    * Test optional end date.
    */
