diff --git a/core/core.services.yml b/core/core.services.yml
index da2d413..99241e4 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -490,7 +490,7 @@ services:
     arguments: ['@module_handler']
   date:
     class: Drupal\Core\Datetime\Date
-    arguments: ['@config.factory', '@language_manager']
+    arguments: ['@plugin.manager.entity', '@language_manager']
   feed.bridge.reader:
     class: Drupal\Component\Bridge\ZfExtensionManagerSfContainer
     calls:
diff --git a/core/lib/Drupal/Core/Datetime/Date.php b/core/lib/Drupal/Core/Datetime/Date.php
index 45aa3be..5567331 100644
--- a/core/lib/Drupal/Core/Datetime/Date.php
+++ b/core/lib/Drupal/Core/Datetime/Date.php
@@ -2,14 +2,14 @@
 
 /**
  * @file
- * Contains \Drupal\Component\Datetime\Date.
+ * Contains \Drupal\Core\Datetime\Date.
  */
 
 namespace Drupal\Core\Datetime;
 
 use Drupal\Component\Utility\Xss;
-use Drupal\Core\Config\ConfigFactory;
 use Drupal\Core\Datetime\DrupalDateTime;
+use Drupal\Core\Entity\EntityManager;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Language\LanguageManager;
 
@@ -26,11 +26,11 @@ class Date {
   protected $timezones;
 
   /**
-   * The config factory.
+   * The date format storage.
    *
-   * @var \Drupal\Core\Config\ConfigFactory
+   * @var \Drupal\Core\Entity\EntityStorageControllerInterface
    */
-  protected $configFactory;
+  protected $dateFormatStorage;
 
   /**
    * Language manager for retrieving the default langcode when none is specified.
@@ -40,15 +40,15 @@ class Date {
   protected $languageManager;
 
   /**
-   * Constructs a DateFormats object.
+   * Constructs a Date object.
    *
-   * @param \Drupal\Core\Config\ConfigFactory $config_factory
-   *   The config factory.
+   * @param \Drupal\Core\Entity\EntityManager $entity_manager
+   *   The entity manager.
    * @param \Drupal\Core\Language\LanguageManager $language_manager
    *   The language manager.
    */
-  public function __construct(ConfigFactory $config_factory, LanguageManager $language_manager) {
-    $this->configFactory = $config_factory;
+  public function __construct(EntityManager $entity_manager, LanguageManager $language_manager) {
+    $this->dateFormatStorage = $entity_manager->getStorageController('date_format');
     $this->languageManager = $language_manager;
   }
 
@@ -103,14 +103,13 @@ public function format($timestamp, $type = 'medium', $format = '', $timezone = N
     $key = $date->canUseIntl() ? DrupalDateTime::INTL : DrupalDateTime::PHP;
 
     // If we have a non-custom date format use the provided date format pattern.
-    $config = $this->configFactory->get('system.date');
-    if ($type != 'custom') {
-      $format = $config->get('formats.' . $type . '.pattern.' . $key);
+    if ($date_format = $this->dateFormatStorage->load($type)) {
+      $format = $date_format->getPattern($key);
     }
 
     // Fall back to medium if a format was not found.
     if (empty($format)) {
-      $format = $config->get('formats.medium.pattern.' . $key);
+      $format = $this->dateFormatStorage->load('fallback')->getPattern($key);
     }
 
     // Call $date->format().
diff --git a/core/modules/datetime/datetime.module b/core/modules/datetime/datetime.module
index d2c35db..856162c 100644
--- a/core/modules/datetime/datetime.module
+++ b/core/modules/datetime/datetime.module
@@ -32,16 +32,27 @@
 function datetime_element_info() {
   $format_type = datetime_default_format_type();
 
+  $date_format = '';
+  $time_format = '';
+  // Date formats cannot be loaded during install or update.
+  if (!defined('MAINTENANCE_MODE')) {
+    if ($date_format_entity = entity_load('date_format', 'html_date')) {
+      $date_format = $date_format_entity->getPattern($format_type);
+    }
+    if ($time_format_entity = entity_load('date_format', 'html_time')) {
+      $time_format = $time_format_entity->getPattern($format_type);
+    }
+  }
   $types['datetime'] = array(
     '#input' => TRUE,
     '#element_validate' => array('datetime_datetime_validate'),
     '#process' => array('datetime_datetime_form_process'),
     '#theme' => 'datetime_form',
     '#theme_wrappers' => array('datetime_wrapper'),
-    '#date_date_format' => config('system.date')->get('formats.html_date.pattern.' . $format_type),
+    '#date_date_format' => $date_format,
     '#date_date_element' => 'date',
     '#date_date_callbacks' => array(),
-    '#date_time_format' => config('system.date')->get('formats.html_time.pattern.' . $format_type),
+    '#date_time_format' => $time_format,
     '#date_time_element' => 'time',
     '#date_time_callbacks' => array(),
     '#date_year_range' => '1900:2050',
@@ -429,7 +440,7 @@ function theme_datetime_wrapper($variables) {
  *     list of the possible formats and HTML5 standards for the HTML5
  *     requirements. Defaults to the right HTML5 format for the chosen element
  *     if a HTML5 element is used, otherwise defaults to
- *     config('system.date')->get('formats.html_date.pattern.php').
+ *     entity_load('date_format', 'html_date')->getPattern().
  *   - #date_date_element: The date element. Options are:
  *     - datetime: Use the HTML5 datetime element type.
  *     - datetime-local: Use the HTML5 datetime-local element type.
@@ -449,7 +460,7 @@ function theme_datetime_wrapper($variables) {
  *     a list of the possible formats and HTML5 standards for the HTML5
  *     requirements. Defaults to the right HTML5 format for the chosen element
  *     if a HTML5 element is used, otherwise defaults to
- *     config('system.date')->get('formats.html_time.pattern.php').
+ *     entity_load('date_format', 'html_time')->getPattern().
  *   - #date_time_callbacks: An array of optional callbacks for the time
  *     element. Can be used to add a jQuery timepicker or an 'All day' checkbox.
  *   - #date_year_range: A description of the range of years to allow, like
@@ -710,11 +721,11 @@ function datetime_html5_format($part, $element) {
     case 'date':
       switch ($element['#date_date_element']) {
         case 'date':
-          return config('system.date')->get('formats.html_date.pattern.' . $format_type);
+          return entity_load('date_format', 'html_date')->getPattern($format_type);
 
         case 'datetime':
         case 'datetime-local':
-          return config('system.date')->get('formats.html_datetime.pattern.' . $format_type);
+          return entity_load('date_format', 'html_datetime')->getPattern($format_type);
 
         default:
           return $element['#date_date_format'];
@@ -724,7 +735,7 @@ function datetime_html5_format($part, $element) {
     case 'time':
       switch ($element['#date_time_element']) {
         case 'time':
-          return config('system.date')->get('formats.html_time.pattern.' . $format_type);
+          return entity_load('date_format', 'html_time')->getPattern($format_type);
 
         default:
           return $element['#date_time_format'];
@@ -1140,9 +1151,9 @@ function datetime_form_node_form_alter(&$form, &$form_state, $form_id) {
 
   // Alter the 'Authored on' date to use datetime.
   $form['author']['date']['#type'] = 'datetime';
-  $config = Drupal::config('system.date');
-  $format = $config->get('formats.html_date.pattern.' . $format_type) . ' ' . $config->get('formats.html_time.pattern.' . $format_type);
-  $form['author']['date']['#description'] = t('Format: %format. Leave blank to use the time of form submission.', array('%format' => datetime_format_example($format)));
+  $date_format = entity_load('date_format', 'html_date')->getPattern($format_type);
+  $time_format = entity_load('date_format', 'html_time')->getPattern($format_type);
+  $form['author']['date']['#description'] = t('Format: %format. Leave blank to use the time of form submission.', array('%format' => datetime_format_example($date_format . ' ' . $time_format)));
   unset($form['author']['date']['#maxlength']);
 }
 
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php
index 729c44e..88a2184 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php
@@ -9,10 +9,14 @@
 
 use Drupal\field\Annotation\FieldFormatter;
 use Drupal\Core\Annotation\Translation;
-use Drupal\field\Plugin\Type\Formatter\FormatterBase;
-use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Datetime\Date;
 use Drupal\Core\Datetime\DrupalDateTime;
-use Drupal\Core\Template\Attribute;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\field\Plugin\Type\Formatter\FormatterBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Plugin implementation of the 'datetime_default' formatter.
@@ -29,7 +33,64 @@
  *   }
  * )
  */
-class DateTimeDefaultFormatter extends FormatterBase {
+class DateTimeDefaultFormatter extends FormatterBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * The date service.
+   *
+   * @var \Drupal\Core\Datetime\Date
+   */
+  protected $dateService;
+
+  /**
+   * The date storage controller.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageControllerInterface
+   */
+  protected $dateStorage;
+
+  /**
+   * Constructs a new DateTimeDefaultFormatter.
+   *
+   * @param string $plugin_id
+   *   The plugin_id for the formatter.
+   * @param array $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Entity\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 \Drupal\Core\Datetime\Date $date_service
+   *   The date service.
+   * @param \Drupal\Core\Entity\EntityStorageControllerInterface $date_storage
+   *   The date storage controller.
+   */
+  public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, Date $date_service, EntityStorageControllerInterface $date_storage) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode);
+
+    $this->dateService = $date_service;
+    $this->dateStorage = $date_storage;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
+    return new static(
+      $plugin_id,
+      $plugin_definition,
+      $configuration['field_definition'],
+      $configuration['settings'],
+      $configuration['label'],
+      $configuration['view_mode'],
+      $container->get('date'),
+      $container->get('plugin.manager.entity')->getStorageController('date_format')
+    );
+  }
 
   /**
    * {@inheritdoc}
@@ -89,22 +150,18 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) {
    */
   function dateFormat($date) {
     $format_type = $this->getSetting('format_type');
-    return format_date($date->getTimestamp(), $format_type);
+    return $this->dateService->format($date->getTimestamp(), $format_type);
   }
 
   /**
    * {@inheritdoc}
    */
   public function settingsForm(array $form, array &$form_state) {
-
-    $element = array();
-
     $time = new DrupalDateTime();
-    $format_types = system_get_date_formats();
-    if (!empty($format_types)) {
-      foreach ($format_types as $type => $type_info) {
-        $options[$type] = $type_info['name'] . ' (' . format_date($time->format('U'), $type) . ')';
-      }
+    $format_types = $this->dateStorage->loadMultiple();
+    foreach ($format_types as $type => $type_info) {
+      $format = $this->dateService->format($time->format('U'), $type);
+      $options[$type] = $type_info->label() . ' (' . $format . ')';
     }
 
     $elements['format_type'] = array(
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php
index 79f12bc..5fd0a1e 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php
@@ -31,6 +31,13 @@
 class DateTimeDefaultWidget extends WidgetBase {
 
   /**
+   * The date format storage.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageControllerInterface
+   */
+  protected $dateStorage;
+
+  /**
    * {@inheritdoc}
    */
   public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings) {
@@ -41,6 +48,9 @@ public function __construct($plugin_id, array $plugin_definition, FieldDefinitio
       $field_definition->default_value_function = $this->defaultValueFunction();
     }
     parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings);
+
+    // @todo Inject this once https://drupal.org/node/2035317 is in.
+    $this->dateStorage = \Drupal::entityManager()->getStorageController('date_format');
   }
 
   /**
@@ -74,7 +84,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
       case 'date':
         $date_type = 'date';
         $time_type = 'none';
-        $date_format = config('system.date')->get('formats.html_date.pattern.' . $format_type);
+        $date_format = $this->dateStorage->load('html_date')->getPattern($format_type);
         $time_format = '';
         $element_format = $date_format;
         $storage_format = DATETIME_DATE_STORAGE_FORMAT;
@@ -83,8 +93,8 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
       default:
         $date_type = 'date';
         $time_type = 'time';
-        $date_format = config('system.date')->get('formats.html_date.pattern.' . $format_type);
-        $time_format = config('system.date')->get('formats.html_time.pattern.' . $format_type);
+        $date_format = $this->dateStorage->load('html_date')->getPattern($format_type);
+        $time_format = $this->dateStorage->load('html_time')->getPattern($format_type);
         $element_format = $date_format . ' ' . $time_format;
         $storage_format = DATETIME_DATETIME_STORAGE_FORMAT;
         break;
diff --git a/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php b/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php
index a0538d7..af66e0d 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php
@@ -104,8 +104,8 @@ function testDateField() {
     $value = '2012-12-31 00:00:00';
     $date = new DrupalDateTime($value);
     $format_type = $date->canUseIntl() ? DrupalDateTime::INTL : DrupalDateTime::PHP;
-    $date_format = config('system.date')->get('formats.html_date.pattern.' . $format_type);
-    $time_format = config('system.date')->get('formats.html_time.pattern.' . $format_type);
+    $date_format = entity_load('date_format', 'html_date')->getPattern($format_type);
+    $time_format = entity_load('date_format', 'html_time')->getPattern($format_type);
 
     $edit = array(
       'user_id' => 1,
@@ -175,8 +175,8 @@ function testDatetimeField() {
     $value = '2012-12-31 00:00:00';
     $date = new DrupalDateTime($value);
     $format_type = $date->canUseIntl() ? DrupalDateTime::INTL : DrupalDateTime::PHP;
-    $date_format = config('system.date')->get('formats.html_date.pattern.' . $format_type);
-    $time_format = config('system.date')->get('formats.html_time.pattern.' . $format_type);
+    $date_format = entity_load('date_format', 'html_date')->getPattern($format_type);
+    $time_format = entity_load('date_format', 'html_time')->getPattern($format_type);
 
     $edit = array(
       'user_id' => 1,
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
index f3cb4cb..6eb0c9a 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
@@ -58,6 +58,15 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac
   public function createInstance($plugin_id, array $configuration) {
     $plugin_definition = $this->discovery->getDefinition($plugin_id);
     $plugin_class = DefaultFactory::getPluginClass($plugin_id, $plugin_definition);
+
+    // @todo This is copied from \Drupal\Core\Plugin\Factory\ContainerFactory.
+    //   Find a way to restore sanity to
+    //   \Drupal\field\Plugin\Type\Formatter\FormatterBase::__construct().
+    // If the plugin provides a factory method, pass the container to it.
+    if (is_subclass_of($plugin_class, 'Drupal\Core\Plugin\ContainerFactoryPluginInterface')) {
+      return $plugin_class::create(\Drupal::getContainer(), $configuration, $plugin_id, $plugin_definition);
+    }
+
     return new $plugin_class($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['label'], $configuration['view_mode']);
   }
 
diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install
index eac6fa4..b781421 100644
--- a/core/modules/locale/locale.install
+++ b/core/modules/locale/locale.install
@@ -948,22 +948,14 @@ function locale_update_8015() {
  * Converts localized date formats.
  */
 function locale_update_8016() {
-  $configs = array();
-
   // Fetch all date types from {date_format_type}.
   $result = db_query('SELECT * FROM {date_format_locale}');
   foreach ($result as $format) {
     $language = $format->language;
     // Create config objects for the language if not yet done.
-    if (!isset($configs[$language])) {
-      $configs[$language] = config('locale.config.' . $language . '.system.date');
-    }
-    $configs[$language]->set('formats.' . $format->type . '.pattern.php', $format->format);
-  }
-
-  // Save all instantiated config objects.
-  foreach ($configs as $config) {
-    $config->save();
+    config("locale.config.$language.system.date_format." . $format->type)
+      ->set('pattern.php', $format->format)
+      ->save();
   }
 }
 
diff --git a/core/modules/system/config/system.date.yml b/core/modules/system/config/system.date.yml
index 55c6e75..55a35c1 100644
--- a/core/modules/system/config/system.date.yml
+++ b/core/modules/system/config/system.date.yml
@@ -1,64 +1,3 @@
 first_day: '0'
 country:
   default: ''
-formats:
-  long:
-    name: 'Default Long Date'
-    pattern:
-      php: 'l, F j, Y - H:i'
-      intl: 'EEEE, LLLL d, yyyy - kk:mm'
-    locked: 0
-  medium:
-    name: 'Default Medium Date'
-    pattern:
-      php: 'D, m/d/Y - H:i'
-      intl: 'ccc, MM/dd/yyyy - kk:mm'
-    locked: 0
-  short:
-    name: 'Default Short Date'
-    pattern:
-      php: 'm/d/Y - H:i'
-      intl: 'MM/dd/yyyy - kk:mm'
-    locked: 0
-  html_datetime:
-    name: 'HTML Datetime'
-    pattern:
-      php: 'Y-m-d\TH:i:sO'
-      intl: 'yyyy-MM-dd''T''kk:mm:ssZZ'
-    locked: 1
-  html_date:
-    name: 'HTML Date'
-    pattern:
-      php: 'Y-m-d'
-      intl: 'yyyy-MM-dd'
-    locked: 1
-  html_time:
-    name: 'HTML Time'
-    pattern:
-      php: 'H:i:s'
-      intl: 'H:mm:ss'
-    locked: 1
-  html_yearless_date:
-    name: 'HTML Yearless date'
-    pattern:
-      php: 'm-d'
-      intl: 'MM-d'
-    locked: 1
-  html_week:
-    name: 'HTML Week'
-    pattern:
-      php: 'Y-\WW'
-      intl: 'Y-''W''WW'
-    locked: 1
-  html_month:
-    name: 'HTML Month'
-    pattern:
-      php: 'Y-m'
-      intl: 'Y-MM'
-    locked: 1
-  html_year:
-    name: 'HTML Year'
-    pattern:
-      php: 'Y'
-      intl: 'Y'
-    locked: 1
diff --git a/core/modules/system/config/system.date_format.fallback.yml b/core/modules/system/config/system.date_format.fallback.yml
new file mode 100644
index 0000000..a9e3eb1
--- /dev/null
+++ b/core/modules/system/config/system.date_format.fallback.yml
@@ -0,0 +1,10 @@
+id: fallback
+uuid: cf0ad071-ded7-4750-b008-8c74f200ff8d
+label: 'Fallback date format'
+status: '1'
+langcode: en
+locked: '1'
+locales: {  }
+pattern:
+  php: 'D, m/d/Y - H:i'
+  intl: 'ccc, MM/dd/yyyy - kk:mm'
diff --git a/core/modules/system/config/system.date_format.html_date.yml b/core/modules/system/config/system.date_format.html_date.yml
new file mode 100644
index 0000000..6d4e004
--- /dev/null
+++ b/core/modules/system/config/system.date_format.html_date.yml
@@ -0,0 +1,10 @@
+id: html_date
+uuid: f4028e7f-3ed8-4737-8f27-39b618214a1f
+label: 'HTML Date'
+status: '1'
+langcode: en
+locked: '1'
+locales: {  }
+pattern:
+  php: Y-m-d
+  intl: yyyy-MM-dd
diff --git a/core/modules/system/config/system.date_format.html_datetime.yml b/core/modules/system/config/system.date_format.html_datetime.yml
new file mode 100644
index 0000000..624f935
--- /dev/null
+++ b/core/modules/system/config/system.date_format.html_datetime.yml
@@ -0,0 +1,10 @@
+id: html_datetime
+uuid: bfd7db46-607f-477f-9047-713c312dbb02
+label: 'HTML Datetime'
+status: '1'
+langcode: en
+locked: '1'
+locales: {  }
+pattern:
+  php: 'Y-m-d\TH:i:sO'
+  intl: 'yyyy-MM-dd''T''kk:mm:ssZZ'
diff --git a/core/modules/system/config/system.date_format.html_month.yml b/core/modules/system/config/system.date_format.html_month.yml
new file mode 100644
index 0000000..92fe715
--- /dev/null
+++ b/core/modules/system/config/system.date_format.html_month.yml
@@ -0,0 +1,10 @@
+id: html_month
+uuid: f85dd1b6-0edb-4024-a800-bb8c87805b2b
+label: 'HTML Month'
+status: '1'
+langcode: en
+locked: '1'
+locales: {  }
+pattern:
+  php: Y-m
+  intl: Y-MM
diff --git a/core/modules/system/config/system.date_format.html_time.yml b/core/modules/system/config/system.date_format.html_time.yml
new file mode 100644
index 0000000..a2aaf35
--- /dev/null
+++ b/core/modules/system/config/system.date_format.html_time.yml
@@ -0,0 +1,10 @@
+id: html_time
+uuid: f8e87532-396e-4353-b02c-4493d2031bc6
+label: 'HTML Time'
+status: '1'
+langcode: en
+locked: '1'
+locales: {  }
+pattern:
+  php: 'H:i:s'
+  intl: 'H:mm:ss'
diff --git a/core/modules/system/config/system.date_format.html_week.yml b/core/modules/system/config/system.date_format.html_week.yml
new file mode 100644
index 0000000..aa45e8e
--- /dev/null
+++ b/core/modules/system/config/system.date_format.html_week.yml
@@ -0,0 +1,10 @@
+id: html_week
+uuid: d14737ae-d1e0-436b-9225-37113d4c8c7c
+label: 'HTML Week'
+status: '1'
+langcode: en
+locked: '1'
+locales: {  }
+pattern:
+  php: Y-\WW
+  intl: 'Y-''W''WW'
diff --git a/core/modules/system/config/system.date_format.html_year.yml b/core/modules/system/config/system.date_format.html_year.yml
new file mode 100644
index 0000000..731cc5f
--- /dev/null
+++ b/core/modules/system/config/system.date_format.html_year.yml
@@ -0,0 +1,10 @@
+id: html_year
+uuid: a43b8034-a2f2-4507-9400-bed7d389265f
+label: 'HTML Year'
+status: '1'
+langcode: en
+locked: '1'
+locales: {  }
+pattern:
+  php: Y
+  intl: Y
diff --git a/core/modules/system/config/system.date_format.html_yearless_date.yml b/core/modules/system/config/system.date_format.html_yearless_date.yml
new file mode 100644
index 0000000..29240b2
--- /dev/null
+++ b/core/modules/system/config/system.date_format.html_yearless_date.yml
@@ -0,0 +1,10 @@
+id: html_yearless_date
+uuid: 623ab5ae-ebba-42cc-b100-a4ca10c77b2e
+label: 'HTML Yearless date'
+status: '1'
+langcode: en
+locked: '1'
+locales: {  }
+pattern:
+  php: m-d
+  intl: MM-d
diff --git a/core/modules/system/config/system.date_format.long.yml b/core/modules/system/config/system.date_format.long.yml
new file mode 100644
index 0000000..4c632c5
--- /dev/null
+++ b/core/modules/system/config/system.date_format.long.yml
@@ -0,0 +1,10 @@
+id: long
+uuid: 500ad047-44b4-429f-9b00-d54df9cbaa8c
+label: 'Default long date'
+status: '1'
+langcode: en
+locked: '0'
+locales: {  }
+pattern:
+  php: 'l, F j, Y - H:i'
+  intl: 'EEEE, LLLL d, yyyy - kk:mm'
diff --git a/core/modules/system/config/system.date_format.medium.yml b/core/modules/system/config/system.date_format.medium.yml
new file mode 100644
index 0000000..35946a8
--- /dev/null
+++ b/core/modules/system/config/system.date_format.medium.yml
@@ -0,0 +1,10 @@
+id: medium
+uuid: 17a8d708-e3b1-432d-9d36-542a97346a60
+label: 'Default medium date'
+status: '1'
+langcode: en
+locked: '0'
+locales: {  }
+pattern:
+  php: 'D, m/d/Y - H:i'
+  intl: 'ccc, MM/dd/yyyy - kk:mm'
diff --git a/core/modules/system/config/system.date_format.short.yml b/core/modules/system/config/system.date_format.short.yml
new file mode 100644
index 0000000..e72c134
--- /dev/null
+++ b/core/modules/system/config/system.date_format.short.yml
@@ -0,0 +1,10 @@
+id: short
+uuid: a8ee7b86-5ef8-43a5-b200-d2e40e10cd58
+label: 'Default short date'
+status: '1'
+langcode: en
+locked: '0'
+locales: {  }
+pattern:
+  php: 'm/d/Y - H:i'
+  intl: 'MM/dd/yyyy - kk:mm'
diff --git a/core/modules/system/lib/Drupal/system/DateFormatAccessController.php b/core/modules/system/lib/Drupal/system/DateFormatAccessController.php
new file mode 100644
index 0000000..9608271
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/DateFormatAccessController.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\DateFormatAccessController.
+ */
+
+namespace Drupal\system;
+
+use Drupal\Core\Entity\EntityAccessController;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Session\AccountInterface;
+
+/**
+ * Provides an access controller for date formats.
+ */
+class DateFormatAccessController extends EntityAccessController {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
+    // There are no restrictions on viewing a date format.
+    if ($operation == 'view') {
+      return TRUE;
+    }
+    // Locked date formats cannot be updated or deleted.
+    if (in_array($operation, array('update', 'delete')) && $entity->isLocked()) {
+      return FALSE;
+    }
+    return user_access('administer site configuration', $account);
+  }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/DateFormatInterface.php b/core/modules/system/lib/Drupal/system/DateFormatInterface.php
new file mode 100644
index 0000000..6801494
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/DateFormatInterface.php
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\DateFormatInterface.
+ */
+
+namespace Drupal\system;
+
+use Drupal\Core\Config\Entity\ConfigEntityInterface;
+use Drupal\Core\Datetime\DrupalDateTime;
+
+/**
+ * Provides an interface defining a date format.
+ */
+interface DateFormatInterface extends ConfigEntityInterface {
+
+  /**
+   * Gets the date pattern string for this format.
+   *
+   * @param string $type
+   *   The date pattern type to set.
+   *
+   * @return string
+   *   The pattern string as expected by date().
+   */
+  public function getPattern($type = DrupalDateTime::PHP);
+
+  /**
+   * Sets the date pattern for this format.
+   *
+   * @param string $pattern
+   *   The date pattern to use for this format.
+   * @param string $type
+   *   The date pattern type to set.
+   *
+   * @return self
+   *   Returns the date format.
+   */
+  public function setPattern($pattern, $type = DrupalDateTime::PHP);
+
+  /**
+   * Adds a locale for this date format.
+   *
+   * @param string $locale
+   *   The locale to add for this format.
+   *
+   * @return self
+   *   Returns the date format.
+   */
+  public function addLocale($locale);
+
+  /**
+   * Sets the locales for this date format. This overwrites existing locales.
+   *
+   * @param array $locales
+   *   The array of locales to set for this format.
+   *
+   * @return self
+   *   Returns the date format.
+   */
+  public function setLocales(array $locales);
+
+  /**
+   * Returns an array of the locales for this date format.
+   *
+   * @return array
+   *   An array of locale names.
+   */
+  public function getLocales();
+
+  /**
+   * Determines if this data format has any locales.
+   *
+   * @return bool
+   *   TRUE if the date format has locales, FALSE otherwise.
+   */
+  public function hasLocales();
+
+  /**
+   * Determines if this date format is locked.
+   *
+   * @return bool
+   *   TRUE if the date format is locked, FALSE otherwise.
+   */
+  public function isLocked();
+
+}
diff --git a/core/modules/system/lib/Drupal/system/DateFormatListController.php b/core/modules/system/lib/Drupal/system/DateFormatListController.php
new file mode 100644
index 0000000..e08c825
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/DateFormatListController.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\DateFormatListController.
+ */
+
+namespace Drupal\system;
+
+use Drupal\Component\Utility\String;
+use Drupal\Core\Config\Entity\ConfigEntityListController;
+use Drupal\Core\Datetime\Date;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a listing of date formats.
+ */
+class DateFormatListController extends ConfigEntityListController {
+
+  /**
+   * The date service.
+   *
+   * @var \Drupal\Core\Datetime\Date
+   */
+  protected $dateService;
+
+  /**
+   * Constructs a new DateFormatListController object.
+   *
+   * @param string $entity_type
+   *   The type of entity to be listed.
+   * @param array $entity_info
+   *   An array of entity info for the entity type.
+   * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage
+   *   The entity storage controller class.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler to invoke hooks on.
+   * @param \Drupal\Core\Datetime\Date $date_service
+   *   The date service.
+   */
+  public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, Date $date_service) {
+    parent::__construct($entity_type, $entity_info, $storage, $module_handler);
+
+    $this->dateService = $date_service;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
+    return new static(
+      $entity_type,
+      $entity_info,
+      $container->get('plugin.manager.entity')->getStorageController($entity_type),
+      $container->get('module_handler'),
+      $container->get('date')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    return array_filter(parent::load(), function ($entity) {
+      return !$entity->isLocked();
+    });
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildHeader() {
+    $header['id'] = t('Machine name');
+    $header['label'] = t('Name');
+    $header['pattern'] = t('Pattern');
+    $header['operations'] = t('Operations');
+    return $header;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildRow(EntityInterface $entity) {
+    $row['id'] = $entity->id();
+    $row['label'] = String::checkPlain($entity->label());
+    $row['pattern'] = $this->dateService->format(REQUEST_TIME, $entity->id());
+    $row['operations']['data'] = $this->buildOperations($entity);
+    return $row;
+  }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Form/DateFormatAddForm.php b/core/modules/system/lib/Drupal/system/Form/DateFormatAddForm.php
index 6dec855..8305e52 100644
--- a/core/modules/system/lib/Drupal/system/Form/DateFormatAddForm.php
+++ b/core/modules/system/lib/Drupal/system/Form/DateFormatAddForm.php
@@ -8,86 +8,25 @@
 namespace Drupal\system\Form;
 
 /**
- * Provides an add form for date formats.
+ * Provides a form controller for adding a date format.
  */
 class DateFormatAddForm extends DateFormatFormBase {
 
   /**
    * {@inheritdoc}
    */
-  public function getFormID() {
-    return 'date_format_add';
+  protected function actions(array $form, array &$form_state) {
+    $actions = parent::actions($form, $form_state);
+    $actions['submit']['#value'] = t('Add format');
+    return $actions;
   }
 
   /**
    * {@inheritdoc}
    */
-  public function buildForm(array $form, array &$form_state) {
-    form_load_include($form_state, 'admin.inc', 'system');
-    $form['date_format_name'] = array(
-      '#type' => 'textfield',
-      '#title' => 'Name',
-      '#maxlength' => 100,
-      '#description' => t('Name of the date format'),
-      '#default_value' => '',
-    );
-
-    $form['date_format_id'] = array(
-      '#type' => 'machine_name',
-      '#title' => t('Machine-readable name'),
-      '#description' => t('A unique machine-readable name. Can only contain lowercase letters, numbers, and underscores.'),
-      '#default_value' => '',
-      '#machine_name' => array(
-        'exists' => 'system_date_format_exists',
-        'source' => array('date_format_name'),
-      ),
-    );
-
-    if (class_exists('intlDateFormatter')) {
-      $description = t('A user-defined date format. See the <a href="@url">PHP manual</a> for available options.', array('@url' => 'http://userguide.icu-project.org/formatparse/datetime'));
-    }
-    else {
-      $description = t('A user-defined date format. See the <a href="@url">PHP manual</a> for available options.', array('@url' => 'http://php.net/manual/function.date.php'));
-    }
-    $form['date_format_pattern'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Format string'),
-      '#maxlength' => 100,
-      '#description' => $description,
-      '#default_value' => '',
-      '#field_suffix' => ' <small id="edit-date-format-suffix"></small>',
-      '#ajax' => array(
-        'callback' => 'system_date_time_lookup',
-        'event' => 'keyup',
-        'progress' => array('type' => 'throbber', 'message' => NULL),
-      ),
-      '#required' => TRUE,
-    );
-
-    $languages = language_list();
-
-    $options = array();
-    foreach ($languages as $langcode => $data) {
-      $options[$langcode] = $data->name;
-    }
-
-    if (!empty($options)) {
-      $form['date_langcode'] = array(
-        '#title' => t('Select localizations'),
-        '#type' => 'select',
-        '#options' => $options,
-        '#multiple' => TRUE,
-        '#default_value' => '',
-      );
-    }
-
-    $form['actions'] = array('#type' => 'actions');
-    $form['actions']['update'] = array(
-      '#type' => 'submit',
-      '#value' => t('Add format'),
-    );
-
-    return $form;
+  public function submit(array $form, array &$form_state) {
+    parent::submit($form, $form_state);
+    drupal_set_message(t('Custom date format added.'));
   }
 
 }
diff --git a/core/modules/system/lib/Drupal/system/Form/DateFormatDeleteForm.php b/core/modules/system/lib/Drupal/system/Form/DateFormatDeleteForm.php
index 327fb3f..3d3dfc7 100644
--- a/core/modules/system/lib/Drupal/system/Form/DateFormatDeleteForm.php
+++ b/core/modules/system/lib/Drupal/system/Form/DateFormatDeleteForm.php
@@ -7,68 +7,56 @@
 
 namespace Drupal\system\Form;
 
-use Drupal\Core\Form\ConfirmFormBase;
 use Drupal\Core\Controller\ControllerInterface;
-use Drupal\Core\Config\ConfigFactory;
+use Drupal\Core\Datetime\Date;
+use Drupal\Core\Entity\EntityConfirmFormBase;
+use Drupal\Core\Entity\EntityControllerInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
-use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Builds a form to delete a date format.
  */
-class DateFormatDeleteForm extends ConfirmFormBase implements ControllerInterface {
+class DateFormatDeleteForm extends EntityConfirmFormBase implements EntityControllerInterface {
 
   /**
-   * The date format data to be deleted.
+   * The date service.
    *
-   * @var array
+   * @var \Drupal\Core\Datetime\Date
    */
-  protected $format;
+  protected $dateService;
 
   /**
-   * The ID of the date format to be deleted.
+   * Constructs an DateFormatDeleteForm object.
    *
-   * @var string
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler service.
+   * @param \Drupal\Core\Datetime\Date $date_service
+   *   The date service.
    */
-  protected $formatID;
+  public function __construct(ModuleHandlerInterface $module_handler, Date $date_service) {
+    parent::__construct($module_handler);
 
-  /**
-   * The config factory.
-   *
-   * @var \Drupal\Core\Config\ConfigFactory
-   */
-  protected $configFactory;
-
-  /**
-   * Constructs a DateFormatDeleteForm object.
-   */
-  public function __construct(ConfigFactory $config_factory) {
-    $this->configFactory = $config_factory;
+    $this->dateService = $date_service;
   }
 
   /**
    * {@inheritdoc}
    */
-  public static function create(ContainerInterface $container) {
+  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
     return new static(
-      $container->get('config.factory')
+      $container->get('module_handler'),
+      $container->get('date')
     );
   }
 
   /**
    * {@inheritdoc}
    */
-  public function getFormID() {
-    return 'system_date_delete_format_form';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function getQuestion() {
     return t('Are you sure you want to remove the format %name : %format?', array(
-      '%name' => $this->format['name'],
-      '%format' => format_date(REQUEST_TIME, $this->formatID))
+      '%name' => $this->entity->label(),
+      '%format' => $this->dateService->format(REQUEST_TIME, $this->entity->id()))
     );
   }
 
@@ -83,31 +71,17 @@ public function getConfirmText() {
    * {@inheritdoc}
    */
   public function getCancelPath() {
-    return 'admin/config/regional/date-time/formats';
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   * @param string $format_id
-   *   The date format ID.
-   */
-  public function buildForm(array $form, array &$form_state, $format_id = NULL, Request $request = NULL) {
-    // We don't get the format ID in the returned format array.
-    $this->formatID = $format_id;
-    $this->format = $this->configFactory->get('system.date')->get("formats.$format_id");
-
-    return parent::buildForm($form, $form_state, $request);
+    return 'admin/config/regional/date-time';
   }
 
   /**
    * {@inheritdoc}
    */
-  public function submitForm(array &$form, array &$form_state) {
-    system_date_format_delete($this->formatID);
-    drupal_set_message(t('Removed date format %format.', array('%format' => $this->format['name'])));
+  public function submit(array $form, array &$form_state) {
+    $this->entity->delete();
+    drupal_set_message(t('Removed date format %format.', array('%format' => $this->entity->label())));
 
-    $form_state['redirect'] = 'admin/config/regional/date-time/formats';
+    $form_state['redirect'] = 'admin/config/regional/date-time';
   }
 
 }
diff --git a/core/modules/system/lib/Drupal/system/Form/DateFormatEditForm.php b/core/modules/system/lib/Drupal/system/Form/DateFormatEditForm.php
index 9af75b2..ebf4df8 100644
--- a/core/modules/system/lib/Drupal/system/Form/DateFormatEditForm.php
+++ b/core/modules/system/lib/Drupal/system/Form/DateFormatEditForm.php
@@ -7,125 +7,40 @@
 
 namespace Drupal\system\Form;
 
-use Drupal\Core\Config\ConfigFactory;
-use Drupal\Core\Controller\ControllerInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
 /**
- * Provides an edit form for date formats.
+ * Provides a form controller for editing a date format.
  */
-class DateFormatEditForm extends DateFormatFormBase implements ControllerInterface {
+class DateFormatEditForm extends DateFormatFormBase {
 
   /**
-   * The config object.
-   *
-   * @var \Drupal\Core\Config\Config
-   */
-  protected $config;
-
-  /**
-   * Constructs a new date format form.
-   *
-   * @param \Drupal\Core\Config\ConfigFactory $config_factory
-   *   The config factory object.
+   * {@inheritdoc}
    */
-  public function __construct(ConfigFactory $config_factory) {
-    parent::__construct();
+  public function form(array $form, array &$form_state) {
+    $form = parent::form($form, $form_state);
 
-    $this->config = $config_factory->get('system.date');
-  }
+    $now = t('Displayed as %date', array('%date' => $this->dateService->format(REQUEST_TIME, $this->entity->id())));
+    $form['date_format_pattern']['#field_suffix'] = ' <small id="edit-date-format-suffix">' . $now . '</small>';
+    $form['date_format_pattern']['#default_value'] = $this->entity->getPattern($this->patternType);
 
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('config.factory')
-    );
+    return $form;
   }
 
   /**
    * {@inheritdoc}
    */
-  public function getFormID() {
-    return 'date_format_edit';
+  protected function actions(array $form, array &$form_state) {
+    $actions = parent::actions($form, $form_state);
+    $actions['submit']['#value'] = t('Save format');
+    unset($actions['delete']);
+    return $actions;
   }
 
   /**
    * {@inheritdoc}
    */
-  public function buildForm(array $form, array &$form_state, $date_format_id = NULL) {
-    form_load_include($form_state, 'admin.inc', 'system');
-    $format_info = $this->config->get('formats.' . $date_format_id);
-    $pattern = $this->patternType ? $format_info['pattern'][$this->patternType] : '';
-
-    $form['date_format_name'] = array(
-      '#type' => 'textfield',
-      '#title' => 'Name',
-      '#maxlength' => 100,
-      '#description' => t('Name of the date format'),
-      '#default_value' => empty($format_info['name']) ? '' : $format_info['name']
-    );
-
-    $now = t('Displayed as %date', array('%date' => format_date(REQUEST_TIME, $date_format_id)));
-
-    $form['date_format_id'] = array(
-      '#type' => 'machine_name',
-      '#title' => t('Machine-readable name'),
-      '#description' => t('A unique machine-readable name. Can only contain lowercase letters, numbers, and underscores.'),
-      '#disabled' => !empty($date_format_id),
-      '#default_value' => $date_format_id,
-      '#machine_name' => array(
-        'exists' => 'system_date_format_exists',
-        'source' => array('date_format_name'),
-      ),
-    );
-
-    if (class_exists('intlDateFormatter')) {
-      $description = t('A user-defined date format. See the <a href="@url">PHP manual</a> for available options.', array('@url' => 'http://userguide.icu-project.org/formatparse/datetime'));
-    }
-    else {
-      $description = t('A user-defined date format. See the <a href="@url">PHP manual</a> for available options.', array('@url' => 'http://php.net/manual/function.date.php'));
-    }
-    $form['date_format_pattern'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Format string'),
-      '#maxlength' => 100,
-      '#description' => $description,
-      '#default_value' => $pattern,
-      '#field_suffix' => ' <small id="edit-date-format-suffix">' . $now . '</small>',
-      '#ajax' => array(
-        'callback' => 'system_date_time_lookup',
-        'event' => 'keyup',
-        'progress' => array('type' => 'throbber', 'message' => NULL),
-      ),
-      '#required' => TRUE,
-    );
-
-    $languages = language_list();
-
-    $options = array();
-    foreach ($languages as $langcode => $data) {
-      $options[$langcode] = $data->name;
-    }
-
-    if (!empty($options)) {
-      $form['date_langcode'] = array(
-        '#title' => t('Select localizations'),
-        '#type' => 'select',
-        '#options' => $options,
-        '#multiple' => TRUE,
-        '#default_value' => empty($format_info['locales']) ? '' : $format_info['locales']
-      );
-    }
-
-    $form['actions'] = array('#type' => 'actions');
-    $form['actions']['update'] = array(
-      '#type' => 'submit',
-      '#value' => t('Save format'),
-    );
-
-    return $form;
+  public function submit(array $form, array &$form_state) {
+    parent::submit($form, $form_state);
+    drupal_set_message(t('Custom date format updated.'));
   }
 
 }
diff --git a/core/modules/system/lib/Drupal/system/Form/DateFormatFormBase.php b/core/modules/system/lib/Drupal/system/Form/DateFormatFormBase.php
index eef17d8..4d347c5 100644
--- a/core/modules/system/lib/Drupal/system/Form/DateFormatFormBase.php
+++ b/core/modules/system/lib/Drupal/system/Form/DateFormatFormBase.php
@@ -7,14 +7,20 @@
 
 namespace Drupal\system\Form;
 
+use Drupal\Core\Ajax\AjaxResponse;
+use Drupal\Core\Ajax\ReplaceCommand;
+use Drupal\Core\Datetime\Date;
+use Drupal\Core\Entity\EntityControllerInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\Core\Datetime\DrupalDateTime;
-use Drupal\Core\Form\FormInterface;
-use Drupal\Component\Utility\String;
+use Drupal\Core\Entity\Query\QueryFactory;
+use Drupal\Core\Entity\EntityFormController;
 
 /**
- * Provides a base form for date formats.
+ * Provides a base form controller for date formats.
  */
-abstract class DateFormatFormBase implements FormInterface {
+abstract class DateFormatFormBase extends EntityFormController implements EntityControllerInterface {
 
   /**
    * The date pattern type.
@@ -24,48 +30,189 @@
   protected $patternType;
 
   /**
+   * The entity query factory.
+   *
+   * @var \Drupal\Core\Entity\Query\QueryFactory
+   */
+  protected $queryFactory;
+
+  /**
+   * The date service.
+   *
+   * @var \Drupal\Core\Datetime\Date
+   */
+  protected $dateService;
+
+  /**
    * Constructs a new date format form.
+   *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler.
+   * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
+   *   The entity query factory.
+   * @param \Drupal\Core\Datetime\Date $date_service
+   *   The date service.
    */
-  public function __construct() {
+  function __construct(ModuleHandlerInterface $module_handler, QueryFactory $query_factory, Date $date_service) {
+    parent::__construct($module_handler);
+
     $date = new DrupalDateTime();
     $this->patternType = $date->canUseIntl() ? DrupalDateTime::INTL : DrupalDateTime::PHP;
+
+    $this->queryFactory = $query_factory;
+    $this->dateService = $date_service;
   }
 
   /**
    * {@inheritdoc}
    */
-  public function validateForm(array &$form, array &$form_state) {
-    $formats = system_get_date_formats();
-    $format = trim($form_state['values']['date_format_pattern']);
+  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
+    return new static(
+      $container->get('module_handler'),
+      $container->get('entity.query'),
+      $container->get('date')
+    );
+  }
 
-    // The machine name field should already check to see if the requested
-    // machine name is available. Regardless of machine_name or human readable
-    // name, check to see if the provided pattern exists.
-    if (!empty($formats) && in_array($format, array_values($formats)) && (!isset($form_state['values']['date_format_id']) || $form_state['values']['date_format_id'] != $formats[$format]['date_format_id'])) {
-      form_set_error('date_format', t('This format already exists. Enter a unique format string.'));
+  /**
+   * Checks for an existing date format.
+   *
+   * @param string|int $entity_id
+   *   The entity ID.
+   * @param array $element
+   *   The form element.
+   * @param array $form_state
+   *   The form state.
+   *
+   * @return bool
+   *   TRUE if this format already exists, FALSE otherwise.
+   */
+  public function exists($entity_id, array $element,  array $form_state) {
+    return (bool) $this->queryFactory
+      ->get($this->entity->entityType())
+      ->condition('id', $element['#field_prefix'] . $entity_id)
+      ->execute();
+  }
+
+  /**
+   * Returns the date for a given format string.
+   *
+   * @param array $form
+   *   An associative array containing the structure of the form.
+   * @param array $form_state
+   *   An associative array containing the current state of the form.
+   *
+   * @return \Drupal\Core\Ajax\AjaxResponse
+   *   An AJAX Response to update the date-time value of the date format.
+   */
+  public static function dateTimeLookup(array $form, array $form_state) {
+    $format = '';
+    if (!empty($form_state['values']['date_format_pattern'])) {
+      $format = t('Displayed as %date_format', array('%date_format' => \Drupal::service('date')->format(REQUEST_TIME, 'custom', $form_state['values']['date_format_pattern'])));
     }
+    // Return a command instead of a string, since the Ajax framework
+    // automatically prepends an additional empty DIV element for a string, which
+    // breaks the layout.
+    $response = new AjaxResponse();
+    $response->addCommand(new ReplaceCommand('#edit-date-format-suffix', '<small id="edit-date-format-suffix">' . $format . '</small>'));
+    return $response;
   }
 
   /**
    * {@inheritdoc}
    */
-  public function submitForm(array &$form, array &$form_state) {
-    $format = array();
-    $format['name'] = String::checkPlain($form_state['values']['date_format_name']);
-    $format['pattern'][$this->patternType] = trim($form_state['values']['date_format_pattern']);
-    $format['locales'] = !empty($form_state['values']['date_langcode']) ? $form_state['values']['date_langcode'] : array();
-    // Formats created in the UI are not locked.
-    $format['locked'] = 0;
-
-    system_date_format_save($form_state['values']['date_format_id'], $format);
-    if (!empty($form_state['values']['date_format_id'])) {
-      drupal_set_message(t('Custom date format updated.'));
+  public function form(array $form, array &$form_state) {
+    $form['label'] = array(
+      '#type' => 'textfield',
+      '#title' => 'Name',
+      '#maxlength' => 100,
+      '#description' => t('Name of the date format'),
+      '#default_value' => $this->entity->label(),
+    );
+
+    $form['id'] = array(
+      '#type' => 'machine_name',
+      '#title' => t('Machine-readable name'),
+      '#description' => t('A unique machine-readable name. Can only contain lowercase letters, numbers, and underscores.'),
+      '#disabled' => !$this->entity->isNew(),
+      '#default_value' => $this->entity->id(),
+      '#machine_name' => array(
+        'exists' => array($this, 'exists'),
+      ),
+    );
+
+    if (class_exists('intlDateFormatter')) {
+      $description = t('A user-defined date format. See the <a href="@url">PHP manual</a> for available options.', array('@url' => 'http://userguide.icu-project.org/formatparse/datetime'));
     }
     else {
-      drupal_set_message(t('Custom date format added.'));
+      $description = t('A user-defined date format. See the <a href="@url">PHP manual</a> for available options.', array('@url' => 'http://php.net/manual/function.date.php'));
+    }
+    $form['date_format_pattern'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Format string'),
+      '#maxlength' => 100,
+      '#description' => $description,
+      '#default_value' => '',
+      '#field_suffix' => ' <small id="edit-date-format-suffix"></small>',
+      '#ajax' => array(
+        'callback' => array($this, 'dateTimeLookup'),
+        'event' => 'keyup',
+        'progress' => array('type' => 'throbber', 'message' => NULL),
+      ),
+      '#required' => TRUE,
+    );
+
+    $languages = language_list();
+
+    $options = array();
+    foreach ($languages as $langcode => $data) {
+      $options[$langcode] = $data->name;
+    }
+
+    if (!empty($options)) {
+      $form['locales'] = array(
+        '#title' => t('Select localizations'),
+        '#type' => 'select',
+        '#options' => $options,
+        '#multiple' => TRUE,
+        '#default_value' => $this->entity->getLocales(),
+      );
     }
 
-    $form_state['redirect'] = 'admin/config/regional/date-time/formats';
+    return parent::form($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validate(array $form, array &$form_state) {
+    parent::validate($form, $form_state);
+
+    // The machine name field should already check to see if the requested
+    // machine name is available. Regardless of machine_name or human readable
+    // name, check to see if the provided pattern exists.
+    $format = trim($form_state['values']['date_format_pattern']);
+    $formats = $this->queryFactory
+      ->get($this->entity->entityType())
+      ->condition('pattern.' . $this->patternType, $format)
+      ->execute();
+
+    // Exclude the current format.
+    unset($formats[$this->entity->id()]);
+    if (!empty($formats)) {
+      form_set_error('date_format_pattern', t('This format already exists. Enter a unique format string.'));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submit(array $form, array &$form_state) {
+    $form_state['redirect'] = 'admin/config/regional/date-time';
+    $form_state['values']['pattern'][$this->patternType] = trim($form_state['values']['date_format_pattern']);
+
+    parent::submit($form, $form_state);
+    $this->entity->save();
   }
 
 }
diff --git a/core/modules/system/lib/Drupal/system/Form/DateFormatLocalizeResetForm.php b/core/modules/system/lib/Drupal/system/Form/DateFormatLocalizeResetForm.php
index b2efd41..d3de481 100644
--- a/core/modules/system/lib/Drupal/system/Form/DateFormatLocalizeResetForm.php
+++ b/core/modules/system/lib/Drupal/system/Form/DateFormatLocalizeResetForm.php
@@ -102,7 +102,9 @@ public function buildForm(array $form, array &$form_state, $langcode = NULL, Req
    * {@inheritdoc}
    */
   public function submitForm(array &$form, array &$form_state) {
-    $this->configFactory->get('locale.config.' . $this->language->id . '.system.date')->delete();
+    foreach (config_get_storage_names_with_prefix('locale.config.' . $this->language->id . '.system.date_format.') as $config_id) {
+      $this->configFactory->get($config_id)->delete();
+    }
 
     $form_state['redirect'] = 'admin/config/regional/date-time/locale';
   }
diff --git a/core/modules/system/lib/Drupal/system/Plugin/Core/Entity/DateFormat.php b/core/modules/system/lib/Drupal/system/Plugin/Core/Entity/DateFormat.php
new file mode 100644
index 0000000..badf567
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Plugin/Core/Entity/DateFormat.php
@@ -0,0 +1,201 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Plugin\Core\Entity\DateFormat.
+ */
+
+namespace Drupal\system\Plugin\Core\Entity;
+
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\Core\Datetime\DrupalDateTime;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\system\DateFormatInterface;
+use Drupal\Core\Entity\Annotation\EntityType;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Defines the Date Format configuration entity class.
+ *
+ * @EntityType(
+ *   id = "date_format",
+ *   label = @Translation("Date format"),
+ *   module = "system",
+ *   controllers = {
+ *     "storage" = "Drupal\Core\Config\Entity\ConfigStorageController",
+ *     "access" = "Drupal\system\DateFormatAccessController",
+ *     "list" = "Drupal\system\DateFormatListController",
+ *     "form" = {
+ *       "add" = "Drupal\system\Form\DateFormatAddForm",
+ *       "edit" = "Drupal\system\Form\DateFormatEditForm",
+ *       "delete" = "Drupal\system\Form\DateFormatDeleteForm"
+ *     }
+ *   },
+ *   config_prefix = "system.date_format",
+ *   entity_keys = {
+ *     "id" = "id",
+ *     "label" = "label",
+ *     "uuid" = "uuid"
+ *   }
+ * )
+ */
+class DateFormat extends ConfigEntityBase implements DateFormatInterface {
+
+  /**
+   * The date format machine name.
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * The date format UUID.
+   *
+   * @var string
+   */
+  public $uuid;
+
+  /**
+   * The human-readable name of the date format entity.
+   *
+   * @var string
+   */
+  public $label;
+
+  /**
+   * The date format pattern.
+   *
+   * @var array
+   */
+  protected $pattern;
+
+  /**
+   * The locked status of this date format.
+   *
+   * @var bool
+   */
+  protected $locked = FALSE;
+
+  /**
+   * @var array
+   */
+  protected $locales = array();
+
+  /**
+   * {@inheritdoc}
+   */
+  public function uri() {
+    return array(
+      'path' => 'admin/config/regional/date-time/formats/manage/' . $this->id(),
+      'options' => array(
+        'entity_type' => $this->entityType,
+        'entity' => $this,
+      ),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getExportProperties() {
+    $properties = parent::getExportProperties();
+    $names = array(
+      'locked',
+      'locales',
+      'pattern',
+    );
+    foreach ($names as $name) {
+      $properties[$name] = $this->get($name);
+    }
+    return $properties;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPattern($type = DrupalDateTime::PHP) {
+    return isset($this->pattern[$type]) ? $this->pattern[$type] : '';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setPattern($pattern, $type = DrupalDateTime::PHP) {
+    $this->pattern[$type] = $pattern;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLocales() {
+    return $this->locales;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setLocales(array $locales) {
+    $this->locales = $locales;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function hasLocales() {
+    return !empty($this->locales);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addLocale($locale) {
+    $this->locales[] = $locale;
+    $this->locales = array_unique($this->locales);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isLocked() {
+    return (bool) $this->locked;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function preSave(EntityStorageControllerInterface $storage_controller) {
+    if ($this->hasLocales()) {
+      $config_factory = \Drupal::service('config.factory');
+      $properties = $this->getExportProperties();
+      $languages = language_list();
+      // Check if the suggested language codes are configured.
+      foreach ($this->getLocales() as $langcode) {
+        if (isset($languages[$langcode])) {
+          $config_factory->get('locale.config.' . $langcode . '.system.date_format.' . $this->id())
+            ->setData($properties)
+            ->save();
+        }
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function postDelete(EntityStorageControllerInterface $storage_controller, array $entities) {
+    // Clean up the localized entry if required.
+    if (\Drupal::moduleHandler()->moduleExists('language')) {
+      $languages = language_list();
+      foreach ($entities as $entity) {
+        $format_id = $entity->id();
+        foreach ($languages as $langcode => $data) {
+          config("locale.config.$langcode.system.date_format.$format_id")->delete();
+        }
+      }
+    }
+  }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/FormatDateTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/FormatDateTest.php
index af933e4..6c0d23a 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/FormatDateTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/FormatDateTest.php
@@ -40,11 +40,12 @@ function setUp() {
     config('system.timezone')
       ->set('user.configurable', 1)
       ->save();
-    config('system.date')
-      ->set('formats.long.pattern.php', 'l, j. F Y - G:i')
-      ->set('formats.medium.pattern.php', 'j. F Y - G:i')
-      ->set('formats.short.pattern.php', 'Y M j - g:ia')
-      ->save();
+    $formats = $this->container->get('plugin.manager.entity')
+      ->getStorageController('date_format')
+      ->loadMultiple(array('long', 'medium', 'short'));
+    $formats['long']->setPattern('l, j. F Y - G:i')->save();
+    $formats['medium']->setPattern('j. F Y - G:i')->save();
+    $formats['short']->setPattern('Y M j - g:ia')->save();
 
     variable_set('locale_custom_strings_' . self::LANGCODE, array(
       '' => array('Sunday' => 'domingo'),
@@ -64,25 +65,25 @@ function testAdminDefinedFormatDate() {
 
     // Add new date format.
     $edit = array(
-      'date_format_id' => 'example_style',
-      'date_format_name' => 'Example Style',
+      'id' => 'example_style',
+      'label' => 'Example Style',
       'date_format_pattern' => 'j M y',
     );
     $this->drupalPost('admin/config/regional/date-time/formats/add', $edit, t('Add format'));
 
     // Add a second date format with a different case than the first.
     $edit = array(
-      'date_format_id' => 'example_style_uppercase',
-      'date_format_name' => 'Example Style Uppercase',
+      'id' => 'example_style_uppercase',
+      'label' => 'Example Style Uppercase',
       'date_format_pattern' => 'j M Y',
     );
     $this->drupalPost('admin/config/regional/date-time/formats/add', $edit, t('Add format'));
-    $this->assertText(t('Custom date format updated.'));
+    $this->assertText(t('Custom date format added.'));
 
     $timestamp = strtotime('2007-03-10T00:00:00+00:00');
     $this->assertIdentical(format_date($timestamp, 'example_style', '', 'America/Los_Angeles'), '9 Mar 07', 'Test format_date() using an admin-defined date type.');
     $this->assertIdentical(format_date($timestamp, 'example_style_uppercase', '', 'America/Los_Angeles'), '9 Mar 2007', 'Test format_date() using an admin-defined date type with different case.');
-    $this->assertIdentical(format_date($timestamp, 'undefined_style'), format_date($timestamp, 'medium'), 'Test format_date() defaulting to medium when $type not found.');
+    $this->assertIdentical(format_date($timestamp, 'undefined_style'), format_date($timestamp, 'fallback'), 'Test format_date() defaulting to `fallback` when $type not found.');
   }
 
   /**
diff --git a/core/modules/system/lib/Drupal/system/Tests/Datetime/DateTimePlusIntlTest.php b/core/modules/system/lib/Drupal/system/Tests/Datetime/DateTimePlusIntlTest.php
index 5fe2b82..89466d4 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Datetime/DateTimePlusIntlTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Datetime/DateTimePlusIntlTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Tests\Datetime;
 
 use Drupal\Component\Datetime\DateTimePlus;
+use Drupal\Core\Datetime\DrupalDateTime;
 use Drupal\simpletest\DrupalUnitTestBase;
 
 /**
@@ -75,11 +76,13 @@ function testDateTimestampIntl() {
     $this->assertTrue($intl_date->canUseIntl(), 'DateTimePlus object can use intl when provided with country and langcode settings.');
     $this->assertFalse($php_date->canUseIntl(), 'DateTimePlus object will fallback to use PHP when not provided with country setting.');
 
-    $default_formats = config('system.date')->get('formats');
+    $default_formats = $this->container->get('plugin.manager.entity')
+      ->getStorageController('date_format')
+      ->loadMultiple();
 
     foreach ($default_formats as $format) {
-      $php_format = $php_date->format($format['pattern']['php'], $php_settings);
-      $intl_format = $intl_date->format($format['pattern']['intl'], $intl_settings);
+      $php_format = $php_date->format($format->getPattern(DrupalDateTime::PHP), $php_settings);
+      $intl_format = $intl_date->format($format->getPattern(DrupalDateTime::INTL), $intl_settings);
       $this->assertIdentical($intl_format, $php_format);
     }
   }
diff --git a/core/modules/system/lib/Drupal/system/Tests/System/DateFormatsLanguageTest.php b/core/modules/system/lib/Drupal/system/Tests/System/DateFormatsLanguageTest.php
index 4d98340..27e126a 100644
--- a/core/modules/system/lib/Drupal/system/Tests/System/DateFormatsLanguageTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/System/DateFormatsLanguageTest.php
@@ -60,19 +60,19 @@ function testLocalizeDateFormats() {
 
     // Add new date format for French.
     $edit = array(
-      'date_format_id' => 'example_style_fr',
-      'date_format_name' => 'Example Style',
+      'id' => 'example_style_fr',
+      'label' => 'Example Style',
       'date_format_pattern' => 'd.m.Y - H:i',
-      'date_langcode[]' => array('fr'),
+      'locales[]' => array('fr'),
     );
     $this->drupalPost('admin/config/regional/date-time/formats/add', $edit, t('Add format'));
 
     // Add new date format for English.
     $edit = array(
-      'date_format_id' => 'example_style_en',
-      'date_format_name' => 'Example Style',
+      'id' => 'example_style_en',
+      'label' => 'Example Style',
       'date_format_pattern' => 'j M Y - g:ia',
-      'date_langcode[]' => array('en'),
+      'locales[]' => array('en'),
     );
     $this->drupalPost('admin/config/regional/date-time/formats/add', $edit, t('Add format'));
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/System/DateFormatsLockedTest.php b/core/modules/system/lib/Drupal/system/Tests/System/DateFormatsLockedTest.php
new file mode 100644
index 0000000..e10f106
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/System/DateFormatsLockedTest.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\System\DateFormatsLockedTest.
+ */
+
+namespace Drupal\system\Tests\System;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests the locked functionality of date formats.
+ */
+class DateFormatsLockedTest extends WebTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Locked date formats',
+      'description' => 'Tests the locked functionality of date formats.',
+      'group' => 'System',
+    );
+  }
+
+  /**
+   * Tests attempts at listing, editing, and deleting locked date formats.
+   */
+  public function testDateLocking() {
+    $this->drupalLogin($this->root_user);
+
+    // Locked date formats do not show on the listing page.
+    $this->drupalGet('admin/config/regional/date-time');
+    $this->assertLinkByHref('admin/config/regional/date-time/formats/manage/short');
+    $this->assertNoLinkByHref('admin/config/regional/date-time/formats/manage/html_date');
+
+    // Locked date formats are not editable.
+    $this->drupalGet('admin/config/regional/date-time/formats/manage/short');
+    $this->assertResponse(200);
+    $this->drupalGet('admin/config/regional/date-time/formats/manage/html_date');
+    $this->assertResponse(403);
+
+    // Locked date formats are not deletable.
+    $this->drupalGet('admin/config/regional/date-time/formats/manage/short/delete');
+    $this->assertResponse(200);
+    $this->drupalGet('admin/config/regional/date-time/formats/manage/html_date/delete');
+    $this->assertResponse(403);
+  }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/System/DateTimeTest.php b/core/modules/system/lib/Drupal/system/Tests/System/DateTimeTest.php
index c867581..b9752b4 100644
--- a/core/modules/system/lib/Drupal/system/Tests/System/DateTimeTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/System/DateTimeTest.php
@@ -47,8 +47,8 @@ function testTimeZoneHandling() {
       ->set('default', 'Pacific/Honolulu')
       ->set('user.configurable', 0)
       ->save();
-    config('system.date')
-      ->set('formats.medium.pattern.php', 'Y-m-d H:i:s O')
+    entity_load('date_format', 'medium')
+      ->setPattern('Y-m-d H:i:s O')
       ->save();
 
     // Create some nodes with different authored-on dates.
@@ -78,7 +78,7 @@ function testTimeZoneHandling() {
    */
   function testDateFormatConfiguration() {
     // Confirm 'no custom date formats available' message appears.
-    $this->drupalGet('admin/config/regional/date-time/formats');
+    $this->drupalGet('admin/config/regional/date-time');
 
     // Add custom date format.
     $this->clickLink(t('Add format'));
@@ -86,59 +86,56 @@ function testDateFormatConfiguration() {
     $name = ucwords($date_format_id);
     $date_format = 'd.m.Y - H:i';
     $edit = array(
-      'date_format_id' => $date_format_id,
-      'date_format_name' => $name,
+      'id' => $date_format_id,
+      'label' => $name,
       'date_format_pattern' => $date_format,
     );
     $this->drupalPost('admin/config/regional/date-time/formats/add', $edit, t('Add format'));
-    $this->assertEqual($this->getUrl(), url('admin/config/regional/date-time/formats', array('absolute' => TRUE)), 'Correct page redirection.');
-    $this->assertText(t('Custom date format updated.'), 'Date format added confirmation message appears.');
+    $this->assertEqual($this->getUrl(), url('admin/config/regional/date-time', array('absolute' => TRUE)), 'Correct page redirection.');
+    $this->assertText(t('Custom date format added.'), 'Date format added confirmation message appears.');
     $this->assertText($date_format_id, 'Custom date format appears in the date format list.');
     $this->assertText(t('Delete'), 'Delete link for custom date format appears.');
 
     // Edit custom date format.
-    $this->drupalGet('admin/config/regional/date-time/formats');
+    $this->drupalGet('admin/config/regional/date-time');
     $this->clickLink(t('Edit'));
     $edit = array(
       'date_format_pattern' => 'Y m',
     );
     $this->drupalPost($this->getUrl(), $edit, t('Save format'));
-    $this->assertEqual($this->getUrl(), url('admin/config/regional/date-time/formats', array('absolute' => TRUE)), 'Correct page redirection.');
+    $this->assertEqual($this->getUrl(), url('admin/config/regional/date-time', array('absolute' => TRUE)), 'Correct page redirection.');
     $this->assertText(t('Custom date format updated.'), 'Custom date format successfully updated.');
 
     // Delete custom date format.
     $this->clickLink(t('Delete'));
-    $this->drupalPost('admin/config/regional/date-time/formats/' . $date_format_id . '/delete', array(), t('Remove'));
-    $this->assertEqual($this->getUrl(), url('admin/config/regional/date-time/formats', array('absolute' => TRUE)), 'Correct page redirection.');
+    $this->drupalPost('admin/config/regional/date-time/formats/manage/' . $date_format_id . '/delete', array(), t('Remove'));
+    $this->assertEqual($this->getUrl(), url('admin/config/regional/date-time', array('absolute' => TRUE)), 'Correct page redirection.');
     $this->assertText(t('Removed date format ' . $name), 'Custom date format removed.');
 
     // Make sure the date does not exist in config.
-    $date_format = config('system.date')->get('formats.' . $date_format_id);
-    $this->assertIdentical($date_format, NULL);
+    $date_format = entity_load('date_format', $date_format_id);
+    $this->assertFalse($date_format);
   }
 
   /**
    * Test if the date formats are stored properly.
    */
   function testDateFormatStorage() {
-    $date_format_info = array(
-      'name' => 'testDateFormatStorage Short Format',
+    $date_format = entity_create('date_format', array(
+      'id' => 'test_short',
+      'label' => 'testDateFormatStorage Short Format',
       'pattern' => array('php' => 'dmYHis'),
-    );
-
-    system_date_format_save('test_short', $date_format_info);
+    ));
+    $date_format->save();
 
-    $format = config('system.date')->get('formats.test_short.pattern.php');
+    $format = $date_format->getPattern();
     $this->assertEqual('dmYHis', $format, 'Unlocalized date format resides in general config.');
 
-    $date_format_info['locales'] = array('en');
-
-    system_date_format_save('test_short_en', $date_format_info);
-
-    $format = config('system.date')->get('formats.test_short_en.pattern.php');
+    $date_format->addLocale('en')->save();
+    $format = $date_format->getPattern();
     $this->assertEqual('dmYHis', $format, 'Localized date format resides in general config too.');
 
-    $format = config('locale.config.en.system.date')->get('formats.test_short_en.pattern.php');
+    $format = config('locale.config.en.system.date_format.test_short')->get('pattern.php');
     $this->assertEqual('dmYHis', $format, 'Localized date format resides in localized config.');
   }
 
@@ -146,11 +143,12 @@ function testDateFormatStorage() {
    * Test that date formats are sanitized.
    */
   function testDateFormatXSS() {
-    $date_format_info = array(
-      'name' => 'XSS format',
+    $date_format = entity_create('date_format', array(
+      'id' => 'xss_short',
+      'label' => 'XSS format',
       'pattern' => array('php' => '\<\s\c\r\i\p\t\>\a\l\e\r\t\(\'\X\S\S\'\)\;\<\/\s\c\r\i\p\t\>'),
-    );
-    system_date_format_save('xss_short', $date_format_info);
+    ));
+    $date_format->save();
 
     $this->drupalGet('admin/config/regional/date-time');
     $this->assertNoRaw("<script>alert('XSS');</script>", 'The date format was properly sanitized');
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/DateUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/DateUpgradePathTest.php
index e1720d1..990cbd5 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/DateUpgradePathTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/DateUpgradePathTest.php
@@ -65,12 +65,12 @@ public function testDateUpgrade() {
       'locked' => '0',
     );
 
+    $actual_formats = entity_load_multiple('date_format', array_keys($expected_formats));
     foreach ($expected_formats as $type => $format) {
-      $format_info = config('system.date')->get('formats.' . $type);
-
-      $this->assertEqual($format_info['name'], $format['name'], format_string('Config value for @type name is the same', array('@type' => $type)));
-      $this->assertEqual($format_info['locked'], $format['locked'], format_string('Config value for @type locked is the same', array('@type' => $type)));
-      $this->assertEqual($format_info['pattern']['php'], $format['pattern']['php'], format_string('Config value for @type PHP date pattern is the same', array('@type' => $type)));
+      $format_info = $actual_formats[$type];
+      $this->assertEqual($format_info->label(), $format['name'], format_string('Config value for @type name is the same', array('@type' => $type)));
+      $this->assertEqual($format_info->get('locked'), $format['locked'], format_string('Config value for @type locked is the same', array('@type' => $type)));
+      $this->assertEqual($format_info->getPattern(), $format['pattern']['php'], format_string('Config value for @type PHP date pattern is the same', array('@type' => $type)));
 
       // Make sure that the variable was deleted.
       $this->assertNull(update_variable_get('date_format_' . $type), format_string('Date format variable for @type was deleted.', array('@type' => $type)));
@@ -91,10 +91,10 @@ public function testDateUpgrade() {
       ),
     );
 
-    $config = config('locale.config.de.system.date');
     foreach ($expected_de_formats as $locale_format) {
-      $format = $config->get('formats.' . $locale_format['type'] . '.pattern.php');
+      $format = config('locale.config.de.system.date_format.' . $locale_format['type'])->get('pattern.php');
       $this->assertEqual($locale_format['format'], $format);
     }
   }
+
 }
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index 957db86..a6611c1 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -5,15 +5,12 @@
  * Admin page callbacks for the system module.
  */
 
-use Drupal\Core\Ajax\AjaxResponse;
-use Drupal\Core\Ajax\ReplaceCommand;
-use Symfony\Component\HttpFoundation\JsonResponse;
+use Drupal\system\DateFormatInterface;
+use Drupal\system\Form\ModulesInstallConfirmForm;
+use Drupal\system\Form\ModulesUninstallConfirmForm;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
-use Drupal\Core\Datetime\DrupalDateTime;
-use Drupal\system\Form\ModulesInstallConfirmForm;
-use Drupal\system\Form\ModulesUninstallConfirmForm;
 
 /**
  * Menu callback; Provide the administration overview page.
@@ -1321,69 +1318,6 @@ function theme_system_themes_page($variables) {
 }
 
 /**
- * Displays the date format strings overview page.
- */
-function system_date_time_formats() {
-  $header = array(
-    array('data' => t('Machine name'), 'field' => 'machine_name'),
-    array('data' => t('Name'), 'field' => 'name'),
-    array('data' => t('Pattern'), 'field' => 'pattern'),
-    array('data' => t('Operations'))
-  );
-  $rows = array();
-
-  $formats = system_get_date_formats();
-
-  if (!empty($formats)) {
-    foreach ($formats as $date_format_id => $format_info) {
-      // Do not display date formats that are locked.
-      if (empty($format_info['locked'])) {
-        $row = array();
-        $row[] = array('data' => $date_format_id);
-        $row[] = array('data' => $format_info['name']);
-        $row[] = array('data' => format_date(REQUEST_TIME, $date_format_id));
-
-        // Prepare Operational links.
-        $links = array();
-        $links['edit'] = array(
-          'title' => t('Edit'),
-          'href' => 'admin/config/regional/date-time/formats/' . $date_format_id . '/edit',
-        );
-        $links['delete'] = array(
-          'title' => t('Delete'),
-          'href' => 'admin/config/regional/date-time/formats/' . $date_format_id . '/delete',
-        );
-        $row['operations'] = array('data' => array(
-          '#type' => 'operations',
-          '#links' => $links,
-        ));
-
-        $rows[] = $row;
-      }
-    }
-  }
-
-  $build['date_formats_table'] = array(
-    '#theme' => 'table',
-    '#header' => $header,
-    '#rows' => $rows,
-    '#empty' => t('No custom date formats available. <a href="@link">Add date format</a>.', array('@link' => url('admin/config/regional/date-time/formats/add'))),
-  );
-
-  return $build;
-}
-
-/**
- * Checks if the chosen machine_name exists or not.
- */
-function system_date_format_exists($candidate_machine_name) {
-  if ($formats = system_get_date_formats()) {
-    return array_key_exists($candidate_machine_name, $formats);
-  }
-  return FALSE;
-}
-
-/**
  * Page callback: Displays edit date format links for each language.
  *
  * @see locale_menu()
@@ -1440,25 +1374,23 @@ function system_date_format_localize_form($form, &$form_state, $langcode) {
   );
 
   // Get list of available formats.
-  $formats = system_get_date_formats();
+  $date_service = Drupal::service('date');
+  $formats = Drupal::entityManager()
+    ->getStorageController('date_format')
+    ->loadMultiple();
   $choices = array();
   foreach ($formats as $date_format_id => $format_info) {
     // Ignore values that are localized.
-    if (empty($format_info['locales'])) {
-      $choices[$date_format_id] = format_date(REQUEST_TIME, $date_format_id);
-    }
-    else {
-      unset($formats[$date_format_id]);
+    if (!$format_info->hasLocales()) {
+      $choices[$date_format_id] = $date_service->format(REQUEST_TIME, $date_format_id);
     }
   }
 
   // Get configured formats for each language.
-  $locale_formats = system_date_format_locale($langcode);
-  if (!empty($locale_formats)) {
-    $formats += $locale_formats;
-    foreach ($locale_formats as $date_format_id => $format_info) {
-      $choices[$date_format_id] = format_date(REQUEST_TIME, $date_format_id);
-    }
+  $config_prefix = 'locale.config.' . $langcode . '.system.date_format.';
+  foreach (config_get_storage_names_with_prefix($config_prefix) as $config_id) {
+    $date_format_id = substr($config_id, strlen($config_prefix));
+    $choices[$date_format_id] = $date_service->format(REQUEST_TIME, $date_format_id);
   }
 
   // Display a form field for each format type.
@@ -1466,7 +1398,7 @@ function system_date_format_localize_form($form, &$form_state, $langcode) {
     // Show date format select list.
     $form['date_formats']['date_format_' . $date_format_id] = array(
       '#type' => 'select',
-      '#title' => check_plain($format_info['name']),
+      '#title' => check_plain($format_info->label()),
       '#attributes' => array('class' => array('date-format')),
       '#default_value' => isset($choices[$date_format_id]) ? $date_format_id : 'custom',
       '#options' => $choices,
@@ -1483,32 +1415,16 @@ function system_date_format_localize_form($form, &$form_state, $langcode) {
 }
 
 /**
- * Ajax callback; Returns the date for a given format string.
- */
-function system_date_time_lookup($form, &$form_state) {
-  $format = '';
-  if (!empty($form_state['values']['date_format_pattern'])) {
-    $format = t('Displayed as %date_format', array('%date_format' => format_date(REQUEST_TIME, 'custom', $form_state['values']['date_format_pattern'])));
-  }
-  // Return a command instead of a string, since the Ajax framework
-  // automatically prepends an additional empty DIV element for a string, which
-  // breaks the layout.
-  $response = new AjaxResponse();
-  $response->addCommand(new ReplaceCommand('#edit-date-format-suffix', '<small id="edit-date-format-suffix">' . $format . '</small>'));
-  return $response;
-}
-
-/**
  * Form submission handler for system_date_format_localize_form().
  */
 function system_date_format_localize_form_submit($form, &$form_state) {
   $langcode = $form_state['values']['langcode'];
 
-  $formats = system_get_date_formats();
+  $formats = entity_load_multiple('date_format');
   foreach ($formats as $date_format_id => $format_info) {
     if (isset($form_state['values']['date_format_' . $date_format_id])) {
       $format = $form_state['values']['date_format_' . $date_format_id];
-      system_date_format_localize_form_save($langcode, $date_format_id, $formats[$format]['pattern']);
+      system_date_format_localize_form_save($langcode, $date_format_id, $formats[$format]);
     }
   }
   drupal_set_message(t('Configuration saved.'));
@@ -1549,16 +1465,17 @@ function theme_system_date_format_localize_form($variables) {
 /**
  * Save locale specific date formats to the database.
  *
- * @param $langcode
+ * @param string $langcode
  *   Language code, can be 2 characters, e.g. 'en' or 5 characters, e.g.
  *   'en-CA'.
- * @param $date_format_id
+ * @param string $date_format_id
  *   Date format id, e.g. 'short', 'medium'.
- * @param $format
- *   The date format string.
+ * @param \Drupal\system\DateFormatInterface $format
+ *   The date format entity.
  */
-function system_date_format_localize_form_save($langcode, $date_format_id, $format) {
-  config('locale.config.' . $langcode . '.system.date')
-    ->set('formats.' . $date_format_id . '.pattern', $format)
+function system_date_format_localize_form_save($langcode, $date_format_id, DateFormatInterface $format) {
+  $format->addLocale($langcode)->save();
+  config('locale.config.' . $langcode . '.system.date_format.' . $date_format_id)
+    ->set('pattern', $format->get('pattern'))
     ->save();
 }
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 89f9ddc..f4fe3ce 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -4,7 +4,9 @@
  * @file
  * Install, update and uninstall functions for the system module.
  */
+
 use Drupal\Component\Utility\Crypt;
+use Drupal\Component\Uuid\Uuid;
 use Drupal\Core\Config\FileStorage;
 use Drupal\Core\Database\Database;
 use Drupal\Core\Language\Language;
@@ -1880,33 +1882,51 @@ function system_update_8044() {
 
 /**
  * Convert existing date formats to the new config system.
+ *
+ * @ingroup config_upgrade
  */
 function system_update_8045() {
-  // Get the date config object.
-  $config = config('system.date');
-
+  $uuid = new Uuid();
   // Fetch all date types from {date_format_type}.
   $date_formats = db_query('SELECT * FROM {date_format_type}')->fetchAllAssoc('type', PDO::FETCH_ASSOC);
   if (!empty($date_formats)) {
     foreach ($date_formats as $type => $format) {
       // Set name and locked properties.
-      $config->set("formats.{$type}.name", $format['title']);
-      $config->set("formats.{$type}.locked", $format['locked']);
+      $config = config("system.date_format.$type")
+        ->set('id', $type)
+        ->set('label', $format['title'])
+        ->set('locked', $format['locked'])
+        ->set('status', 1)
+        ->set('uuid', $uuid->generate());
 
       // Get the default date format for this type.
       $variable_name = 'date_format_' . $type;
       $default_format = update_variable_get($variable_name, NULL);
       if ($default_format) {
         // In Drupal 7 we only used PHP date types.
-        $config->set("formats.{$type}.pattern.php", $default_format);
+        $config->set('pattern.php', $default_format);
 
         // Delete the migrated variables.
         update_variable_del($variable_name);
       }
+      // Save the date configuration object.
+      $config->save();
     }
+  }
 
-    // Save the date configuration object.
-    $config->save();
+  // Install the new HTML date formats.
+  $new_formats = array(
+    'system.date_format.fallback',
+    'system.date_format.html_date',
+    'system.date_format.html_datetime',
+    'system.date_format.html_month',
+    'system.date_format.html_time',
+    'system.date_format.html_week',
+    'system.date_format.html_year',
+    'system.date_format.html_yearless_date',
+  );
+  foreach ($new_formats as $new_format) {
+    update_7_to_8_install_default_config('module', $new_format);
   }
 }
 
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index a6a7786..725fcb6 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -845,10 +845,8 @@ function system_menu() {
   $items['admin/config/regional/date-time'] = array(
     'title' => 'Date and time formats',
     'description' => 'Configure display format strings for date and time.',
-    'page callback' => 'system_date_time_formats',
-    'access arguments' => array('administer site configuration'),
+    'route_name' => 'date_format_list',
     'weight' => -9,
-    'file' => 'system.admin.inc',
   );
   $items['admin/config/regional/date-time/formats/add'] = array(
     'title' => 'Add format',
@@ -857,15 +855,12 @@ function system_menu() {
     'route_name' => 'date_format_add',
     'weight' => -10,
   );
-  $items['admin/config/regional/date-time/formats/%/edit'] = array(
+  $items['admin/config/regional/date-time/formats/manage/%'] = array(
     'title' => 'Edit date format',
     'description' => 'Allow users to edit a configured date format.',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('system_configure_date_formats_form', 5),
-    'access arguments' => array('administer site configuration'),
-    'file' => 'system.admin.inc',
+    'route_name' => 'date_format_edit',
   );
-  $items['admin/config/regional/date-time/formats/%/delete'] = array(
+  $items['admin/config/regional/date-time/formats/manage/%/delete'] = array(
     'title' => 'Delete date format',
     'description' => 'Allow users to delete a configured date format.',
     'route_name' => 'date_format_delete',
@@ -2370,26 +2365,6 @@ function system_page_build(&$page) {
 }
 
 /**
- * Select locale date format details from database.
- *
- * @param $languages
- *   An array of language codes.
- *
- * @return
- *   An array of date formats.
- */
-function system_get_localized_date_format($languages) {
-  // Get list of different format types.
-  foreach ($languages as $language) {
-    $date_formats = config('locale.config.' . $language . '.system.date')->get('formats');
-    if (!empty($date_formats)) {
-      return $date_formats;
-    }
-  }
-  return array();
-}
-
-/**
  * Implements hook_custom_theme().
  */
 function system_custom_theme() {
@@ -3428,114 +3403,6 @@ function system_run_automated_cron() {
 }
 
 /**
- * Gets the list of defined date formats and attributes.
- *
- * @return array
- *   An associative array of date formats. The top-level keys are the
- *   machine-readable names of the date formats. The values are associative
- *   arrays with the following keys:
- *   - name: The string human readable name of the date format.
- *   - pattern: An associative array of patterns that will modify the format
- *     of the date, keyed with 'php' for normal PHP date pattern and 'intl'
- *     for the alternate pattern used by the IntlDateFormatter.
- */
-function system_get_date_formats() {
-  return config('system.date')->get('formats');
-}
-
-/**
- * Gets the appropriate date format string for a date type and locale.
- *
- * @param $langcode
- *   (optional) String language code for the current locale. This can be a 2 character
- *   language code like 'en' and 'fr' or a 5 character language code like
- *   'en-gb' and 'en-us'.
- * @param $date_format_id
- *   (optional) String machine name for the date format.
- *
- * @return
- *   If $date_format_id and $langcode are specified, returns the corresponding
- *   date format string. If only $langcode is specified, returns an array of
- *   all date format strings for that locale, keyed by the date type. If
- *   neither is specified returns FALSE.
- */
-function system_date_format_locale($langcode = NULL, $date_format_id = NULL) {
-  $formats = &drupal_static(__FUNCTION__);
-
-  if (!isset($formats[$langcode])) {
-    $formats[$langcode] = config('locale.config.' . $langcode . '.system.date')->get('formats');
-  }
-
-  if ($date_format_id && $langcode && !empty($formats[$langcode][$date_format_id])) {
-    return $formats[$langcode][$date_format_id];
-  }
-  elseif ($langcode && !empty($formats[$langcode])) {
-    return $formats[$langcode];
-  }
-
-  return FALSE;
-}
-
-/**
- * Saves a date format to the database.
- *
- * @param string $date_format_id
- *   If set, replace the existing date format having this ID with the
- *   information specified in $format_info.
- * @param array $format_info
- *   A date format array containing the following keys:
- *   - name: The string name of the date type this format is associated with.
- *   - pattern: An associative array keyed by 'php' and 'intl' with the PHP
- *     and/or IntlDateFormatter date format strings for each.
- *   - locked: A boolean indicating whether or not this format should be
- *     configurable from the user interface.
- *
- * @see http://php.net/date
- */
-function system_date_format_save($date_format_id, $format_info) {
-  config('system.date')
-    ->set('formats.' . $date_format_id, $format_info)
-    ->save();
-
-  $languages = language_list();
-
-  $locale_format = array(
-    'name' => $format_info['name'],
-    'pattern' => $format_info['pattern'],
-  );
-
-  // Check if the suggested language codes are configured.
-  if (!empty($format_info['locales'])) {
-    foreach ($format_info['locales'] as $langcode) {
-      if (isset($languages[$langcode])) {
-        config('locale.config.' . $langcode . '.system.date')
-          ->set('formats.' . $date_format_id, $locale_format)
-          ->save();
-      }
-    }
-  }
-}
-
-/**
- * Deletes a date format from the database.
- *
- * @param $date_format_id
- *   The date format ID.
- */
-function system_date_format_delete($date_format_id) {
-  $format_id = 'formats.' . $date_format_id;
-  config('system.date')->clear($format_id)->save();
-
-  // Clean up the localized entry if required.
-  foreach (language_list() as $langcode => $data) {
-    $config = config('locale.config.' . $langcode . '.system.date');
-    if ($config->get($format_id)) {
-      $config->clear($format_id)->save();
-    }
-  }
-}
-
-/**
  * Returns HTML for a confirmation form.
  *
  * By default this does not alter the appearance of a form at all,
diff --git a/core/modules/system/system.routing.yml b/core/modules/system/system.routing.yml
index 1e09f79..301ab6d 100644
--- a/core/modules/system/system.routing.yml
+++ b/core/modules/system/system.routing.yml
@@ -74,33 +74,40 @@ system_site_maintenance_mode:
   requirements:
     _permission: 'administer site configuration'
 
-date_format_add:
-  pattern: '/admin/config/regional/date-time/formats/add'
+system_run_cron:
+  pattern: '/admin/reports/status/run-cron'
   defaults:
-    _form: '\Drupal\system\Form\DateFormatAddForm'
+    _controller: '\Drupal\system\CronController::runManually'
   requirements:
     _permission: 'administer site configuration'
 
-date_format_edit:
-  pattern: '/admin/config/regional/date-time/formats/{date_format_id}/edit'
+date_format_list:
+  pattern: '/admin/config/regional/date-time'
   defaults:
-    _form: '\Drupal\system\Form\DateFormatEditForm'
+    _entity_list: 'date_format'
   requirements:
     _permission: 'administer site configuration'
 
-system_run_cron:
-  pattern: '/admin/reports/status/run-cron'
+date_format_add:
+  pattern: '/admin/config/regional/date-time/formats/add'
   defaults:
-    _controller: '\Drupal\system\CronController::runManually'
+    _entity_form: 'date_format.add'
   requirements:
     _permission: 'administer site configuration'
 
+date_format_edit:
+  pattern: '/admin/config/regional/date-time/formats/manage/{date_format}'
+  defaults:
+    _entity_form: 'date_format.edit'
+  requirements:
+    _entity_access: 'date_format.update'
+
 date_format_delete:
-  pattern: 'admin/config/regional/date-time/formats/{format_id}/delete'
+  pattern: 'admin/config/regional/date-time/formats/manage/{date_format}/delete'
   defaults:
-    _form: '\Drupal\system\Form\DateFormatDeleteForm'
+    _entity_form: 'date_format.delete'
   requirements:
-    _permission: 'administer site configuration'
+    _entity_access: 'date_format.delete'
 
 date_format_localize_reset:
   pattern: 'admin/config/regional/date-time/locale/{langcode}/reset'
diff --git a/core/modules/user/lib/Drupal/user/Tests/UserTimeZoneTest.php b/core/modules/user/lib/Drupal/user/Tests/UserTimeZoneTest.php
index 8b77915..894555e 100644
--- a/core/modules/user/lib/Drupal/user/Tests/UserTimeZoneTest.php
+++ b/core/modules/user/lib/Drupal/user/Tests/UserTimeZoneTest.php
@@ -30,8 +30,8 @@ function testUserTimeZone() {
       ->set('user.configurable', 1)
       ->set('default', 'America/Los_Angeles')
       ->save();
-    config('system.date')
-      ->set('formats.medium.pattern.php', 'Y-m-d H:i T')
+    entity_load('date_format', 'medium')
+      ->setPattern('Y-m-d H:i T')
       ->save();
 
     // Create a user account and login.
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/field/Date.php b/core/modules/views/lib/Drupal/views/Plugin/views/field/Date.php
index a19c50b..5925990 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/field/Date.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/field/Date.php
@@ -8,6 +8,9 @@
 namespace Drupal\views\Plugin\views\field;
 
 use Drupal\Component\Annotation\PluginID;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\Core\Datetime\Date as DateService;
 
 /**
  * A handler to provide proper displays for dates.
@@ -18,6 +21,54 @@
  */
 class Date extends FieldPluginBase {
 
+  /**
+   * The date service.
+   *
+   * @var \Drupal\Core\Datetime\Date
+   */
+  protected $dateService;
+
+  /**
+   * The date format storage.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageControllerInterface
+   */
+  protected $dateFormatStorage;
+
+  /**
+   * Constructs a new Date object.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin ID for the plugin instance.
+   * @param array $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Datetime\Date $date_service
+   *   The date service.
+   * @param \Drupal\Core\Entity\EntityStorageControllerInterface $date_format_storage
+   *   The date format storage.
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, DateService $date_service, EntityStorageControllerInterface $date_format_storage) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+
+    $this->dateService = $date_service;
+    $this->dateFormatStorage = $date_format_storage;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('date'),
+      $container->get('plugin.manager.entity')->getStorageController('date_format')
+    );
+  }
+
   protected function defineOptions() {
     $options = parent::defineOptions();
 
@@ -31,9 +82,8 @@ protected function defineOptions() {
   public function buildOptionsForm(&$form, &$form_state) {
 
     $date_formats = array();
-    $date_types = system_get_date_formats();
-    foreach ($date_types as $machine_name => $value) {
-      $date_formats[$machine_name] = t('@name format: @date', array('@name' => $value['name'], '@date' => format_date(REQUEST_TIME, $machine_name)));
+    foreach ($this->dateFormatStorage->loadMultiple() as $machine_name => $value) {
+      $date_formats[$machine_name] = t('@name format: @date', array('@name' => $value->label(), '@date' => $this->dateService->format(REQUEST_TIME, $machine_name)));
     }
 
     $form['date_format'] = array(
