diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/DateUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/DateUpgradePathTest.php
new file mode 100644
index 0000000..d0ccd3b
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/DateUpgradePathTest.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Upgrade\DateUpgradePathTest.
+ */
+
+namespace Drupal\system\Tests\Upgrade;
+
+/**
+ * Test upgrade of date formats.
+ */
+class DateUpgradePathTest extends UpgradePathTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Date upgrade test',
+      'description' => 'Upgrade tests for date formats.',
+      'group' => 'Upgrade path',
+    );
+  }
+
+  public function setUp() {
+    $this->databaseDumpFiles = array(
+      drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.bare.standard_all.database.php.gz',
+      drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.date.database.php',
+    );
+    parent::setUp();
+  }
+
+  /**
+   * Tests that date formats have been upgraded.
+   */
+  public function testDateUpgrade() {
+    $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.');
+
+    // Verify standard date formats
+    $expected_formats['short'] = array(
+      'name' => 'Short',
+      'pattern' => array(
+        'php' => 'Y/m/d - H:i',
+      ),
+      'locked' => '1',
+    );
+    $expected_formats['medium'] = array(
+      'name' => 'Medium',
+      'pattern' => array(
+        'php' => 'D, d/m/Y - H:i',
+      ),
+      'locked' => '1',
+    );
+    $expected_formats['long'] = array(
+      'name' => 'Long',
+      'pattern' => array(
+        'php' => 'l, Y,  F j - H:i',
+      ),
+      'locked' => '1',
+    );
+
+    // Verify custom date format
+    $expected_formats['test_custom'] = array(
+      'name' => 'Test Custom',
+      'pattern' => array(
+        'php' => 'd m Y',
+        ),
+      'locked' => '0',
+    );
+
+    foreach ($expected_formats as $type => $format) {
+      $format_info = config('system.date')->get('formats.' . $type);
+
+      $this->assertEqual($format_info['name'], $format['name'], "Config value for {$type} name is the same");
+      $this->assertEqual($format_info['locked'], $format['locked'], "Config value for {$type} locked is the same");
+      $this->assertEqual($format_info['pattern']['php'], $format['pattern']['php'], "Config value for {$type} PHP date pattern is the same");
+    }
+  }
+}
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 5afaf5d..6de9e1f 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -678,95 +678,6 @@ function system_schema() {
   $schema['cache_path'] = $schema['cache'];
   $schema['cache_path']['description'] = 'Cache table for path alias lookup.';
 
-  $schema['date_format_type'] = array(
-    'description' => 'Stores configured date format types.',
-    'fields' => array(
-      'type' => array(
-        'description' => 'The date format type, e.g. medium.',
-        'type' => 'varchar',
-        'length' => 64,
-        'not null' => TRUE,
-      ),
-      'title' => array(
-        'description' => 'The human readable name of the format type.',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-      ),
-      'locked' => array(
-        'description' => 'Whether or not this is a system provided format.',
-        'type' => 'int',
-        'size' => 'tiny',
-        'default' => 0,
-        'not null' => TRUE,
-      ),
-    ),
-    'primary key' => array('type'),
-    'indexes' => array(
-      'title' => array('title'),
-    ),
-  );
-
-  // This table's name is plural as some versions of MySQL can't create a
-  // table named 'date_format'.
-  $schema['date_formats'] = array(
-    'description' => 'Stores configured date formats.',
-    'fields' => array(
-      'dfid' => array(
-        'description' => 'The date format identifier.',
-        'type' => 'serial',
-        'not null' => TRUE,
-        'unsigned' => TRUE,
-      ),
-      'format' => array(
-        'description' => 'The date format string.',
-        'type' => 'varchar',
-        'length' => 100,
-        'not null' => TRUE,
-      ),
-      'type' => array(
-        'description' => 'The date format type, e.g. medium.',
-        'type' => 'varchar',
-        'length' => 64,
-        'not null' => TRUE,
-      ),
-      'locked' => array(
-        'description' => 'Whether or not this format can be modified.',
-        'type' => 'int',
-        'size' => 'tiny',
-        'default' => 0,
-        'not null' => TRUE,
-      ),
-    ),
-    'primary key' => array('dfid'),
-    'unique keys' => array('formats' => array('format', 'type')),
-  );
-
-  $schema['date_format_locale'] = array(
-    'description' => 'Stores configured date formats for each locale.',
-    'fields' => array(
-      'format' => array(
-        'description' => 'The date format string.',
-        'type' => 'varchar',
-        'length' => 100,
-        'not null' => TRUE,
-      ),
-      'type' => array(
-        'description' => 'The date format type, e.g. medium.',
-        'type' => 'varchar',
-        'length' => 64,
-        'not null' => TRUE,
-      ),
-      'language' => array(
-        'description' => 'A {language}.langcode for this format to be used with.',
-        'type' => 'varchar',
-        'length' => 12,
-        'not null' => TRUE,
-      ),
-    ),
-    'primary key' => array('type', 'language'),
-  );
-
   $schema['flood'] = array(
     'description' => 'Flood controls the threshold of events, such as the number of contact attempts.',
     'fields' => array(
@@ -2331,6 +2242,39 @@ function system_update_8041() {
 }
 
 /**
+ * Convert existing date formats to the new config system.
+ */
+function system_update_8042() {
+
+  // Get the date config object.
+  $config = config('system.date');
+
+  // 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']);
+
+      // 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);
+
+        // Delete the migrated variables.
+        db_delete('variable')->condition('name', $variable_name, '=')->execute();
+      }
+    }
+
+    // Save the date configuration object.
+    $config->save();
+  }
+}
+
+/**
  * @} End of "defgroup updates-7.x-to-8.x".
  * The next series of updates should start at 9000.
  */
diff --git a/core/modules/system/tests/upgrade/drupal-7.date.database.php b/core/modules/system/tests/upgrade/drupal-7.date.database.php
new file mode 100644
index 0000000..53c8edb
--- /dev/null
+++ b/core/modules/system/tests/upgrade/drupal-7.date.database.php
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * @file
+ * Database additions for Drupal\system\Tests\Upgrade\DateUpgradePathTest.
+ *
+ * This dump only contains data and schema components relevant for date
+ * functionality. The bare.standard_all.database.php file is imported before
+ * this dump, so the two form the database structure expected in tests
+ * altogether.
+ */
+// Add default format for standard date formats
+db_insert('variable')->fields(array(
+  'name',
+  'value',
+))
+->values(array(
+  'name' => 'date_format_short',
+  'value'=> 's:11:"Y/m/d - H:i";',
+))
+->values(array(
+  'name' => 'date_format_medium',
+  'value'=> 's:14:"D, d/m/Y - H:i";',
+))
+->values(array(
+  'name' => 'date_format_long',
+  'value'=> 's:16:"l, Y,  F j - H:i";',
+))
+->values(array(
+  'name' => 'date_format_test_custom',
+  'value'=> 's:5:"d m Y";',
+))->execute();
+
+// Add custom date formats.
+db_insert('date_format_type')->fields(array(
+  'type',
+  'title',
+  'locked'
+))
+// Custom date format.
+->values(array(
+  'type' => 'test_custom',
+  'title' => 'Test Custom',
+  'locked' => '0',
+))
+->execute();
+
+// Add image effects.
+db_insert('date_formats')->fields(array(
+  'dfid',
+  'format',
+  'type',
+  'locked',
+))
+->values(array(
+  'dfid' => '36',
+  'format' => 'd m Y',
+  'type' => 'test_custom',
+  'locked' => '0',
+))
+->execute();
