diff --git a/core/config/schema/core.entity.schema.yml b/core/config/schema/core.entity.schema.yml
index 90813e5..8a15a4c 100644
--- a/core/config/schema/core.entity.schema.yml
+++ b/core/config/schema/core.entity.schema.yml
@@ -304,9 +304,30 @@ field.formatter.settings.uri_link:
   type: mapping
   label: 'URI as link display format settings'
 
+field.formatter.settings.timestamp:
+  type: mapping
+  label: 'Timestamp display format settings'
+  mapping:
+    date_format:
+      type: string
+      label: 'Date format'
+    custom_date_format:
+      type: string
+      label: 'Custom date format'
+    timezone:
+      type: string
+      label: 'Timezone'
+
 field.formatter.settings.timestamp_ago:
   type: mapping
   label: 'Timestamp ago display format settings'
+  mapping:
+    date_format:
+      type: string
+      label: 'Date format'
+    granularity:
+      type: integer
+      label: 'Granularity'
 
 field.formatter.settings.entity_reference_entity_view:
   type: mapping
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php
index 04f96fa..2ba38bb 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php
@@ -11,6 +11,7 @@
 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;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -82,12 +83,93 @@ public static function create(ContainerInterface $container, array $configuratio
   /**
    * {@inheritdoc}
    */
+  public static function defaultSettings() {
+    return array(
+      'date_format' => 'raw time ago',
+      'granularity' => 2,
+    ) + parent::defaultSettings();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state) {
+    $elements = parent::settingsForm($form, $form_state);
+
+    $elements['date_format'] = array(
+      '#type' => 'select',
+      '#title' => $this->t('Date format'),
+      '#options' => array(
+        'raw time ago' => $this->t('Time ago'),
+        'time ago' => $this->t('Time ago (with "ago" appended)'),
+        'raw time hence' => $this->t('Time hence'),
+        'time hence' => $this->t('Time hence (with "hence" appended)'),
+        'raw time span' => $this->t('Time span (future dates have "-" prepended)'),
+        'inverse time span' => $this->t('Time span (past dates have "-" prepended)'),
+        'time span' => $this->t('Time span (with "ago/hence" appended)'),
+      ),
+      '#default_value' => $this->getSetting('date_format') ?: 'raw time ago',
+    );
+
+    $elements['granularity'] = array(
+      '#type' => 'number',
+      '#title' => $this->t('Granularity'),
+      '#description' => $this->t('How many time units should be shown in the \'time ago\' string.'),
+      '#default_value' => $this->getSetting('granularity') ?: 2,
+      '#min' => 1,
+      '#max' => 7,
+    );
+
+    return $elements;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = parent::settingsSummary();
+
+    $summary[] = $this->t('Date format: @date_format', array('@date_format' => $this->getSetting('date_format')));
+    $summary[] = $this->t('Granularity: @granularity', array('@granularity' => $this->getSetting('granularity')));
+
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function viewElements(FieldItemListInterface $items) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
       if ($item->value) {
-        $updated = $this->t('@time ago', array('@time' => $this->dateFormatter->formatInterval(REQUEST_TIME - $item->value)));
+        $format = $this->getSetting('date_format');
+        $granularity = $this->getSetting('granularity');
+        $time_diff = REQUEST_TIME - $item->value; // will be positive for a datetime in the past (ago), and negative for a datetime in the future (hence)
+        switch ($format) {
+          case 'time ago':
+            $updated = $this->t('%time ago', array('%time' => $this->dateFormatter->formatInterval($time_diff, $granularity)));
+            break;
+          case 'raw time hence':
+            $updated = $this->dateFormatter->formatInterval(-$time_diff, $granularity);
+            break;
+          case 'time hence':
+            $updated = $this->t('%time hence', array('%time' => $this->dateFormatter->formatInterval(-$time_diff, $granularity)));
+            break;
+          case 'raw time span':
+            $updated = ($time_diff < 0 ? '-' : '') . $this->dateFormatter->formatInterval(abs($time_diff), $granularity);
+            break;
+          case 'inverse time span':
+            $updated = ($time_diff > 0 ? '-' : '') . $this->dateFormatter->formatInterval(abs($time_diff), $granularity);
+            break;
+          case 'time span':
+            $updated = $this->t(($time_diff < 0 ? '%time hence' : '%time ago'), array('%time' => $this->dateFormatter->formatInterval(abs($time_diff), $granularity)));
+            break;
+          case 'raw time ago':
+          default:
+            $updated = $this->dateFormatter->formatInterval($time_diff, $granularity);
+            break;
+        }
       }
       else {
         $updated = $this->t('never');
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampFormatter.php
index cb28315..a058410 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampFormatter.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampFormatter.php
@@ -7,8 +7,14 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
 
-use Drupal\Core\Field\FormatterBase;
+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;
+use Drupal\Core\Datetime\DateFormatter;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Plugin implementation of the 'timestamp' formatter.
@@ -23,7 +29,134 @@
  *   }
  * )
  */
-class TimestampFormatter extends FormatterBase {
+class TimestampFormatter extends FormatterBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * The date formatter service.
+   *
+   * @var \Drupal\Core\Datetime\DateFormatter
+   */
+  protected $dateFormatter;
+
+  /**
+   * The date storage.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageInterface
+   */
+  protected $dateStorage;
+
+  /**
+   * Constructs a new DateTimeDefaultFormatter.
+   *
+   * @param string $plugin_id
+   *   The plugin_id for the formatter.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+   *   The definition of the field to which the formatter is associated.
+   * @param array $settings
+   *   The formatter settings.
+   * @param string $label
+   *   The formatter label display setting.
+   * @param string $view_mode
+   *   The view mode.
+   * @param array $third_party_settings
+   *   Third party settings.
+   * @param \Drupal\Core\Datetime\DateFormatter $date_formatter
+   *   The date formatter service.
+   * @param \Drupal\Core\Entity\EntityStorageInterface $date_storage
+   *   The date storage.
+   */
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, DateFormatter $date_formatter, EntityStorageInterface $date_storage) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
+
+    $this->dateFormatter = $date_formatter;
+    $this->dateStorage = $date_storage;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $plugin_id,
+      $plugin_definition,
+      $configuration['field_definition'],
+      $configuration['settings'],
+      $configuration['label'],
+      $configuration['view_mode'],
+      $configuration['third_party_settings'],
+      $container->get('date.formatter'),
+      $container->get('entity.manager')->getStorage('date_format')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    return array(
+      'date_format' => 'medium',
+      'custom_date_format' => '',
+      'timezone' => '',
+    ) + parent::defaultSettings();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state) {
+    $elements = parent::settingsForm($form, $form_state);
+
+    $date_formats = array();
+
+    foreach ($this->dateStorage->loadMultiple() as $machine_name => $value) {
+      $date_formats[$machine_name] = $this->t('@name format: @date', array('@name' => $value->label(), '@date' => $this->dateFormatter->format(REQUEST_TIME, $machine_name)));
+    }
+
+    $date_formats['custom'] = $this->t('Custom');
+
+    $elements['date_format'] = array(
+      '#type' => 'select',
+      '#title' => $this->t('Date format'),
+      '#options' => $date_formats,
+      '#default_value' => $this->getSetting('date_format') ?: 'medium',
+    );
+
+    $elements['custom_date_format'] = array(
+      '#type' => 'textfield',
+      '#title' => $this->t('Custom date format'),
+      '#description' => $this->t('If "Custom", see <a href="http://us.php.net/manual/en/function.date.php" target="_blank">the PHP docs</a> for date formats. Otherwise, enter the number of different time units to display, which defaults to 2.'),
+      '#default_value' => $this->getSetting('custom_date_format') ?: '',
+    );
+
+    $elements['custom_date_format']['#states']['visible'][] = array(
+      ':input[name="options[settings][date_format]"]' => array('value' => 'custom'),
+    );
+
+    $elements['timezone'] = array(
+      '#type' => 'select',
+      '#title' => $this->t('Timezone'),
+      '#description' => $this->t('Timezone to be used for date output.'),
+      '#options' => array('' => $this->t('- Default site/user timezone -')) + system_time_zones(FALSE),
+      '#default_value' => $this->getSetting('timezone'),
+    );
+
+    return $elements;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = parent::settingsSummary();
+
+    $summary[] = $this->t('Date format: @date_format', array('@date_format' => $this->getSetting('date_format')));
+    $summary[] = $this->t('Custom date format: @custom_date_format', array('@custom_date_format' => $this->getSetting('custom_date_format')));
+    $summary[] = $this->t('Timezone: @timezone', array('@timezone' => $this->getSetting('timezone')));
+
+    return $summary;
+  }
 
   /**
    * {@inheritdoc}
@@ -31,6 +164,18 @@ class TimestampFormatter extends FormatterBase {
   public function viewElements(FieldItemListInterface $items) {
     $elements = array();
 
+    $date_format = $this->getSetting('date_format');
+    $custom_date_format = '';
+    $timezone = $this->getSetting('timezone') != '' ?: NULL;
+    $langcode = NULL;
+
+    if ($date_format == 'custom') {
+      $custom_date_format = $this->getSetting('custom_date_format');
+      if ($custom_date_format == 'r') {
+        $langcode = 'en';
+      }
+    }
+
     foreach ($items as $delta => $item) {
       $elements[$delta] = [
         '#cache' => [
@@ -38,7 +183,7 @@ public function viewElements(FieldItemListInterface $items) {
             'timezone',
           ],
         ],
-        '#markup' => format_date($item->value)
+        '#markup' => $this->dateFormatter->format($item->value, $date_format, $custom_date_format, $timezone, $langcode),
       ];
     }
 
diff --git a/core/modules/aggregator/tests/modules/aggregator_test_views/test_views/views.view.test_aggregator_items.yml b/core/modules/aggregator/tests/modules/aggregator_test_views/test_views/views.view.test_aggregator_items.yml
index 8e5673f..166f83f 100644
--- a/core/modules/aggregator/tests/modules/aggregator_test_views/test_views/views.view.test_aggregator_items.yml
+++ b/core/modules/aggregator/tests/modules/aggregator_test_views/test_views/views.view.test_aggregator_items.yml
@@ -78,7 +78,12 @@ display:
           table: aggregator_item
           field: timestamp
           id: timestamp
-          plugin_id: date
+          type: timestamp
+          settings:
+            date_format: medium
+            custom_date_format: ''
+            timezone: ''
+          plugin_id: field
           entity_type: aggregator_item
           entity_field: timestamp
         author:
diff --git a/core/modules/comment/config/optional/views.view.comments_recent.yml b/core/modules/comment/config/optional/views.view.comments_recent.yml
index dd4ba6a..236ba4b 100644
--- a/core/modules/comment/config/optional/views.view.comments_recent.yml
+++ b/core/modules/comment/config/optional/views.view.comments_recent.yml
@@ -118,7 +118,7 @@ display:
           table: comment_field_data
           field: changed
           relationship: none
-          plugin_id: date
+          plugin_id: field
           group_type: group
           admin_label: ''
           label: ''
@@ -162,9 +162,10 @@ display:
           hide_empty: false
           empty_zero: false
           hide_alter_empty: true
-          date_format: 'time ago'
-          custom_date_format: ''
-          timezone: ''
+          type: timestamp_ago
+          settings:
+            date_format: 'time ago'
+            granularity: 2
           entity_type: comment
           entity_field: changed
       filters:
diff --git a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rest.yml b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rest.yml
index 0c53369..30920e2 100644
--- a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rest.yml
+++ b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rest.yml
@@ -245,10 +245,12 @@ display:
           hide_empty: false
           empty_zero: false
           hide_alter_empty: true
-          date_format: long
-          custom_date_format: ''
-          timezone: ''
-          plugin_id: date
+          type: timestamp
+          settings:
+            date_format: long
+            custom_date_format: ''
+            timezone: ''
+          plugin_id: field
         comment_body:
           id: comment_body
           table: comment__comment_body
diff --git a/core/modules/file/config/optional/views.view.files.yml b/core/modules/file/config/optional/views.view.files.yml
index 526d9fd..7843478 100644
--- a/core/modules/file/config/optional/views.view.files.yml
+++ b/core/modules/file/config/optional/views.view.files.yml
@@ -416,10 +416,12 @@ display:
           hide_empty: false
           empty_zero: false
           hide_alter_empty: true
-          date_format: medium
-          custom_date_format: ''
-          timezone: ''
-          plugin_id: date
+          type: timestamp
+          settings:
+            date_format: medium
+            custom_date_format: ''
+            timezone: ''
+          plugin_id: field
           entity_type: file
           entity_field: created
         changed:
@@ -470,10 +472,12 @@ display:
           hide_empty: false
           empty_zero: false
           hide_alter_empty: true
-          date_format: medium
-          custom_date_format: ''
-          timezone: ''
-          plugin_id: date
+          type: timestamp
+          settings:
+            date_format: medium
+            custom_date_format: ''
+            timezone: ''
+          plugin_id: field
           entity_type: file
           entity_field: changed
         count:
diff --git a/core/modules/node/config/optional/views.view.content.yml b/core/modules/node/config/optional/views.view.content.yml
index f431fcc..dff822f 100644
--- a/core/modules/node/config/optional/views.view.content.yml
+++ b/core/modules/node/config/optional/views.view.content.yml
@@ -297,10 +297,12 @@ display:
           hide_empty: false
           empty_zero: false
           hide_alter_empty: true
-          date_format: short
-          custom_date_format: ''
-          timezone: ''
-          plugin_id: date
+          type: timestamp
+          settings:
+            date_format: short
+            custom_date_format: ''
+            timezone: ''
+          plugin_id: field
           entity_type: node
           entity_field: changed
         operations:
diff --git a/core/modules/node/config/optional/views.view.glossary.yml b/core/modules/node/config/optional/views.view.glossary.yml
index b0de110..0876553 100644
--- a/core/modules/node/config/optional/views.view.glossary.yml
+++ b/core/modules/node/config/optional/views.view.glossary.yml
@@ -175,8 +175,12 @@ display:
           table: node_field_data
           field: changed
           label: 'Last update'
-          date_format: long
-          plugin_id: date
+          type: timestamp
+          settings:
+            date_format: long
+            custom_date_format: ''
+            timezone: ''
+          plugin_id: field
           relationship: none
           group_type: group
           admin_label: ''
@@ -220,8 +224,11 @@ display:
           hide_empty: false
           empty_zero: false
           hide_alter_empty: true
-          custom_date_format: ''
-          timezone: ''
+          type: timestamp
+          settings:
+            date_format: medium
+            custom_date_format: ''
+            timezone: ''
           entity_type: node
           entity_field: changed
       arguments:
diff --git a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml
index 49673d5..366cb4a 100644
--- a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml
+++ b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml
@@ -57,7 +57,12 @@ display:
           id: created
           table: views_test_data
           field: created
-          plugin_id: date
+          type: timestamp
+          settings:
+            date_format: medium
+            custom_date_format: ''
+            timezone: ''
+          plugin_id: field
       sorts:
         created:
           id: created
diff --git a/core/modules/statistics/tests/modules/statistics_test_views/test_views/views.view.test_statistics_integration.yml b/core/modules/statistics/tests/modules/statistics_test_views/test_views/views.view.test_statistics_integration.yml
index b8d3c4a..86b63a9 100644
--- a/core/modules/statistics/tests/modules/statistics_test_views/test_views/views.view.test_statistics_integration.yml
+++ b/core/modules/statistics/tests/modules/statistics_test_views/test_views/views.view.test_statistics_integration.yml
@@ -103,10 +103,12 @@ display:
           hide_empty: false
           empty_zero: false
           hide_alter_empty: true
-          date_format: html_year
-          custom_date_format: ''
-          timezone: ''
-          plugin_id: date
+          type: timestamp
+          settings:
+            date_format: medium
+            custom_date_format: ''
+            timezone: ''
+          plugin_id: field
         totalcount:
           id: totalcount
           table: node_counter
diff --git a/core/modules/user/config/optional/views.view.user_admin_people.yml b/core/modules/user/config/optional/views.view.user_admin_people.yml
index 57dd4e4..0b8a4b4 100644
--- a/core/modules/user/config/optional/views.view.user_admin_people.yml
+++ b/core/modules/user/config/optional/views.view.user_admin_people.yml
@@ -399,10 +399,11 @@ display:
           hide_empty: false
           empty_zero: false
           hide_alter_empty: true
-          date_format: 'raw time ago'
-          custom_date_format: ''
-          timezone: ''
-          plugin_id: date
+          type: timestamp_ago
+          settings:
+            date_format: 'raw time ago'
+            granularity: 2
+          plugin_id: field
           entity_type: user
           entity_field: created
         access:
@@ -453,10 +454,11 @@ display:
           hide_empty: false
           empty_zero: false
           hide_alter_empty: true
-          date_format: 'time ago'
-          custom_date_format: ''
-          timezone: ''
-          plugin_id: date
+          type: timestamp_ago
+          settings:
+            date_format: 'time ago'
+            granularity: 2
+          plugin_id: field
           entity_type: user
           entity_field: access
         operations:
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_changed.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_changed.yml
index d929079..f6c0936 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_changed.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_changed.yml
@@ -38,8 +38,12 @@ display:
           table: users_field_data
           field: changed
           label: 'Updated date'
-          date_format: html_date
-          plugin_id: date
+          plugin_id: field
+          type: timestamp
+          settings:
+            date_format: html_date
+            custom_date_format: ''
+            timezone: ''
           entity_type: user
           entity_field: changed
       filters: {  }
diff --git a/core/modules/views/src/EntityViewsData.php b/core/modules/views/src/EntityViewsData.php
index a4099b2..d64f4f5 100644
--- a/core/modules/views/src/EntityViewsData.php
+++ b/core/modules/views/src/EntityViewsData.php
@@ -313,7 +313,7 @@ protected function mapSingleFieldViewsData($table, $field_name, $field_type, $co
       case 'timestamp':
       case 'created':
       case 'changed':
-        $views_field['field']['id'] = 'date';
+        $views_field['field']['id'] = 'field';
         $views_field['argument']['id'] = 'date';
         $views_field['filter']['id'] = 'date';
         $views_field['sort']['id'] = 'date';
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort.yml
index 82d10ad..32632d7 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort.yml
@@ -29,7 +29,12 @@ display:
           table: views_test_data
           field: created
           label: created
-          plugin_id: date
+          plugin_id: field
+          type: timestamp
+          settings:
+            date_format: medium
+            custom_date_format: ''
+            timezone: ''
       access:
         type: none
       cache:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_destroy.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_destroy.yml
index 47bd959..17de27c 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_destroy.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_destroy.yml
@@ -62,7 +62,12 @@ display:
           field: created
           id: created
           table: node_field_data
-          plugin_id: date
+          plugin_id: field
+          type: timestamp
+          settings:
+            date_format: medium
+            custom_date_format: ''
+            timezone: ''
           entity_type: node
           entity_field: created
         nid:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_style_opml.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_style_opml.yml
index e601365..9371bae 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_style_opml.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_style_opml.yml
@@ -238,10 +238,12 @@ display:
           hide_empty: false
           empty_zero: false
           hide_alter_empty: true
-          date_format: html_date
-          custom_date_format: ''
-          timezone: ''
-          plugin_id: date
+          type: timestamp
+          settings:
+            date_format: html_date
+            custom_date_format: ''
+            timezone: ''
+          plugin_id: field
           entity_type: aggregator_feed
           entity_field: modified
       filters: {  }
