diff --git a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeCustomFormatter.php b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeCustomFormatter.php
index 678ddc8..fe5fa75 100644
--- a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeCustomFormatter.php
+++ b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeCustomFormatter.php
@@ -32,30 +32,18 @@ public static function defaultSettings() {
    * {@inheritdoc}
    */
   public function viewElements(FieldItemListInterface $items, $langcode) {
+    // @todo Evaluate removing this method in
+    // https://www.drupal.org/node/2793143 to determine if the behavior and
+    // markup in the base class implementation can be used instead.
     $elements = array();
 
     foreach ($items as $delta => $item) {
-      $output = '';
       if (!empty($item->date)) {
         /** @var \Drupal\Core\Datetime\DrupalDateTime $date */
         $date = $item->date;
 
-        if ($this->getFieldSetting('datetime_type') == 'date') {
-          // A date without time will pick up the current time, use the default.
-          datetime_date_default_time($date);
-        }
-        $this->setTimeZone($date);
-
-        $output = $this->formatDate($date);
+        $elements[$delta] = $this->buildDate($date);
       }
-      $elements[$delta] = [
-        '#markup' => $output,
-        '#cache' => [
-          'contexts' => [
-            'timezone',
-          ],
-        ],
-      ];
     }
 
     return $elements;
diff --git a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeDefaultFormatter.php b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeDefaultFormatter.php
index 3d30e68..152a162 100644
--- a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeDefaultFormatter.php
+++ b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeDefaultFormatter.php
@@ -31,59 +31,6 @@ public static function defaultSettings() {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(FieldItemListInterface $items, $langcode) {
-    $elements = array();
-
-    foreach ($items as $delta => $item) {
-      $output = '';
-      $iso_date = '';
-
-      if ($item->date) {
-        /** @var \Drupal\Core\Datetime\DrupalDateTime $date */
-        $date = $item->date;
-
-        if ($this->getFieldSetting('datetime_type') == 'date') {
-          // A date without time will pick up the current time, use the default.
-          datetime_date_default_time($date);
-        }
-
-        // Create the ISO date in Universal Time.
-        $iso_date = $date->format("Y-m-d\TH:i:s") . 'Z';
-
-        $this->setTimeZone($date);
-
-        $output = $this->formatDate($date);
-      }
-
-      // Display the date using theme datetime.
-      $elements[$delta] = array(
-        '#cache' => [
-          'contexts' => [
-            'timezone',
-          ],
-        ],
-        '#theme' => 'time',
-        '#text' => $output,
-        '#html' => FALSE,
-        '#attributes' => array(
-          'datetime' => $iso_date,
-        ),
-      );
-      if (!empty($item->_attributes)) {
-        $elements[$delta]['#attributes'] += $item->_attributes;
-        // Unset field item attributes since they have been included in the
-        // formatter output and should not be rendered in the field template.
-        unset($item->_attributes);
-      }
-    }
-
-    return $elements;
-
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   protected function formatDate($date) {
     $format_type = $this->getSetting('format_type');
     $timezone = $this->getSetting('timezone_override') ?: $date->getTimezone()->getName();
diff --git a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeFormatterBase.php b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeFormatterBase.php
index be9df38..6a0b01c 100644
--- a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeFormatterBase.php
+++ b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeFormatterBase.php
@@ -6,6 +6,7 @@
 use Drupal\Core\Datetime\DrupalDateTime;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\FormatterBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
@@ -118,6 +119,30 @@ public function settingsSummary() {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public function viewElements(FieldItemListInterface $items, $langcode) {
+    $elements = array();
+
+    foreach ($items as $delta => $item) {
+      if ($item->date) {
+        /** @var \Drupal\Core\Datetime\DrupalDateTime $date */
+        $date = $item->date;
+        $elements[$delta] = $this->buildDateWithIsoAttribute($date);
+
+        if (!empty($item->_attributes)) {
+          $elements[$delta]['#attributes'] += $item->_attributes;
+          // Unset field item attributes since they have been included in the
+          // formatter output and should not be rendered in the field template.
+          unset($item->_attributes);
+        }
+      }
+    }
+
+    return $elements;
+  }
+
+  /**
    * Creates a formatted date value as a string.
    *
    * @param object $date
@@ -167,4 +192,69 @@ protected function getFormatSettings() {
     return $settings;
   }
 
+  /**
+   * Creates a render array from a date object.
+   *
+   * @param \Drupal\Core\Datetime\DrupalDateTime $date
+   *   A date object.
+   *
+   * @return array
+   *   A render array.
+   */
+  protected function buildDate(DrupalDateTime $date) {
+    if ($this->getFieldSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE) {
+      // A date without time will pick up the current time, use the default.
+      datetime_date_default_time($date);
+    }
+    $this->setTimeZone($date);
+
+    $build = [
+      '#plain_text' => $this->formatDate($date),
+      '#cache' => [
+        'contexts' => [
+          'timezone',
+        ],
+      ],
+    ];
+
+    return $build;
+  }
+
+  /**
+   * Creates a render array from a date object with ISO date attribute.
+   *
+   * @param \Drupal\Core\Datetime\DrupalDateTime $date
+   *   A date object.
+   *
+   * @return array
+   *   A render array.
+   */
+  protected function buildDateWithIsoAttribute(DrupalDateTime $date) {
+    if ($this->getFieldSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE) {
+      // A date without time will pick up the current time, use the default.
+      datetime_date_default_time($date);
+    }
+
+    // Create the ISO date in Universal Time.
+    $iso_date = $date->format("Y-m-d\TH:i:s") . 'Z';
+
+    $this->setTimeZone($date);
+
+    $build = [
+      '#theme' => 'time',
+      '#text' => $this->formatDate($date),
+      '#html' => FALSE,
+      '#attributes' => [
+        'datetime' => $iso_date,
+      ],
+      '#cache' => [
+        'contexts' => [
+          'timezone',
+        ],
+      ],
+    ];
+
+    return $build;
+  }
+
 }
diff --git a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimePlainFormatter.php b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimePlainFormatter.php
index 683d75c..5bb6766 100644
--- a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimePlainFormatter.php
+++ b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimePlainFormatter.php
@@ -25,27 +25,12 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
-      $output = '';
       if (!empty($item->date)) {
         /** @var \Drupal\Core\Datetime\DrupalDateTime $date */
         $date = $item->date;
 
-        if ($this->getFieldSetting('datetime_type') == 'date') {
-          // A date without time will pick up the current time, use the default.
-          datetime_date_default_time($date);
-        }
-        $this->setTimeZone($date);
-
-        $output = $this->formatDate($date);
+        $elements[$delta] = $this->buildDate($date);
       }
-      $elements[$delta] = [
-        '#cache' => [
-          'contexts' => [
-            'timezone',
-          ],
-        ],
-        '#markup' => $output,
-      ];
     }
 
     return $elements;
diff --git a/core/modules/datetime_range/src/DateTimeRangeTrait.php b/core/modules/datetime_range/src/DateTimeRangeTrait.php
index 5a34f2c..86fa8b5 100644
--- a/core/modules/datetime_range/src/DateTimeRangeTrait.php
+++ b/core/modules/datetime_range/src/DateTimeRangeTrait.php
@@ -3,6 +3,7 @@
 namespace Drupal\datetime_range;
 
 use Drupal\Core\Datetime\DrupalDateTime;
+use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem;
 
 /**
@@ -11,68 +12,40 @@
 trait DateTimeRangeTrait {
 
   /**
-   * Creates a render array from a date object.
-   *
-   * @param \Drupal\Core\Datetime\DrupalDateTime $date
-   *   A date object.
-   *
-   * @return array
-   *   A render array.
+   * {@inheritdoc}
    */
-  protected function buildDate(DrupalDateTime $date) {
-    if ($this->getFieldSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE) {
-      // A date without time will pick up the current time, use the default.
-      datetime_date_default_time($date);
+  public function viewElements(FieldItemListInterface $items, $langcode) {
+    $elements = [];
+    $separator = $this->getSetting('separator');
+
+    foreach ($items as $delta => $item) {
+      if (!empty($item->start_date) && !empty($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 ($start_date->format('U') !== $end_date->format('U')) {
+          $elements[$delta] = [
+            'start_date' => $this->buildDateWithIsoAttribute($start_date),
+            'separator' => ['#plain_text' => ' ' . $separator . ' '],
+            'end_date' => $this->buildDateWithIsoAttribute($end_date),
+          ];
+        }
+        else {
+          $elements[$delta] = $this->buildDateWithIsoAttribute($start_date);
+
+          if (!empty($item->_attributes)) {
+            $elements[$delta]['#attributes'] += $item->_attributes;
+            // Unset field item attributes since they have been included in the
+            // formatter output and should not be rendered in the field template.
+            unset($item->_attributes);
+          }
+        }
+      }
     }
-    $this->setTimeZone($date);
 
-    $build = [
-      '#plain_text' => $this->formatDate($date),
-      '#cache' => [
-        'contexts' => [
-          'timezone',
-        ],
-      ],
-    ];
-
-    return $build;
-  }
-
-  /**
-   * Creates a render array from a date object with ISO date attribute.
-   *
-   * @param \Drupal\Core\Datetime\DrupalDateTime $date
-   *   A date object.
-   *
-   * @return array
-   *   A render array.
-   */
-  protected function buildDateWithIsoAttribute(DrupalDateTime $date) {
-    if ($this->getFieldSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE) {
-      // A date without time will pick up the current time, use the default.
-      datetime_date_default_time($date);
-    }
-
-    // Create the ISO date in Universal Time.
-    $iso_date = $date->format("Y-m-d\TH:i:s") . 'Z';
-
-    $this->setTimeZone($date);
-
-    $build = [
-      '#theme' => 'time',
-      '#text' => $this->formatDate($date),
-      '#html' => FALSE,
-      '#attributes' => [
-        'datetime' => $iso_date,
-      ],
-      '#cache' => [
-        'contexts' => [
-          'timezone',
-        ],
-      ],
-    ];
-
-    return $build;
+    return $elements;
   }
 
 }
diff --git a/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeCustomFormatter.php b/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeCustomFormatter.php
index a26bbef..78aa8aa 100644
--- a/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeCustomFormatter.php
+++ b/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeCustomFormatter.php
@@ -38,6 +38,9 @@ public static function defaultSettings() {
    * {@inheritdoc}
    */
   public function viewElements(FieldItemListInterface $items, $langcode) {
+    // @todo Evaluate removing this method in
+    // https://www.drupal.org/node/2793143 to determine if the behavior and
+    // markup in the base class implementation can be used instead.
     $elements = [];
     $separator = $this->getSetting('separator');
 
diff --git a/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeDefaultFormatter.php b/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeDefaultFormatter.php
index f07e834..c5c7d8f 100644
--- a/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeDefaultFormatter.php
+++ b/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeDefaultFormatter.php
@@ -38,42 +38,6 @@ public static function defaultSettings() {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(FieldItemListInterface $items, $langcode) {
-    $elements = [];
-    $separator = $this->getSetting('separator');
-
-    foreach ($items as $delta => $item) {
-      if (!empty($item->start_date) && !empty($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 ($start_date->getTimestamp() !== $end_date->getTimestamp()) {
-          $elements[$delta] = [
-            'start_date' => $this->buildDateWithIsoAttribute($start_date),
-            'separator' => ['#plain_text' => ' ' . $separator . ' '],
-            'end_date' => $this->buildDateWithIsoAttribute($end_date),
-          ];
-        }
-        else {
-          $elements[$delta] = $this->buildDateWithIsoAttribute($start_date);
-          if (!empty($item->_attributes)) {
-            $elements[$delta]['#attributes'] += $item->_attributes;
-            // Unset field item attributes since they have been included in the
-            // formatter output and should not be rendered in the field template.
-            unset($item->_attributes);
-          }
-        }
-      }
-    }
-
-    return $elements;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function settingsForm(array $form, FormStateInterface $form_state) {
     $form = parent::settingsForm($form, $form_state);
 
diff --git a/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangePlainFormatter.php b/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangePlainFormatter.php
index 1fb4702..287f451 100644
--- a/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangePlainFormatter.php
+++ b/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangePlainFormatter.php
@@ -37,36 +37,6 @@ public static function defaultSettings() {
   /**
    * {@inheritdoc}
    */
-  public function viewElements(FieldItemListInterface $items, $langcode) {
-    $elements = [];
-    $separator = $this->getSetting('separator');
-
-    foreach ($items as $delta => $item) {
-      if (!empty($item->start_date) && !empty($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 ($start_date->getTimestamp() !== $end_date->getTimestamp()) {
-          $elements[$delta] = [
-            'start_date' => $this->buildDate($start_date),
-            'separator' => ['#plain_text' => ' ' . $separator . ' '],
-            'end_date' => $this->buildDate($end_date),
-          ];
-        }
-        else {
-          $elements[$delta] = $this->buildDate($start_date);
-        }
-      }
-    }
-
-    return $elements;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function settingsForm(array $form, FormStateInterface $form_state) {
     $form = parent::settingsForm($form, $form_state);
 
