diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 02717b448c..fecfc8656e 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -1424,3 +1424,17 @@ function system_element_info_alter(&$type) {
     $type['page']['#theme_wrappers']['off_canvas_page_wrapper'] = ['#weight' => -1000];
   }
 }
+
+/**
+ * Implements hook_date_format_insert().
+ */
+function system_date_format_insert() {
+  \Drupal::token()->resetInfo();
+}
+
+/**
+ * Implements hook_date_format_delete().
+ */
+function system_date_format_delete() {
+  \Drupal::token()->resetInfo();
+}
diff --git a/core/modules/system/system.tokens.inc b/core/modules/system/system.tokens.inc
index a3a670a002..52e1d47b80 100644
--- a/core/modules/system/system.tokens.inc
+++ b/core/modules/system/system.tokens.inc
@@ -65,6 +65,19 @@ function system_token_info() {
     'name' => t("Long format"),
     'description' => t("A date in 'long' format. (%date)", ['%date' => $date_formatter->format(REQUEST_TIME, 'long')]),
   ];
+
+  /** @var \Drupal\Core\Datetime\DateFormatInterface[] $date_formats */
+  $date_formats = \Drupal::entityTypeManager()->getStorage('date_format')->loadMultiple();
+  foreach ($date_formats as $date_format) {
+    $date[$date_format->id()] = [
+      'name' => $date_format->label(),
+      'description' => t("A date in the %name format. (%date)", [
+        '%name' => $date_format->label(),
+        '%date' => format_date(REQUEST_TIME, $date_format->id()),
+      ]),
+    ];
+  }
+
   $date['custom'] = [
     'name' => t("Custom format"),
     'description' => t('A date in a custom format. See <a href="http://php.net/manual/function.date.php">the PHP documentation</a> for details.'),
@@ -165,16 +178,17 @@ function system_tokens($type, $tokens, array $data, array $options, BubbleableMe
       $date = $data['date'];
     }
 
+    /** @var \Drupal\Core\Entity\EntityStorageInterface $date_format_storage */
+    $date_format_storage = \Drupal::entityTypeManager()->getStorage('date_format');
     foreach ($tokens as $name => $original) {
+      // Date type token replacement.
+      $date_format = $date_format_storage->load($name);
+      if ($date_format) {
+        $bubbleable_metadata->addCacheableDependency($date_format);
+        $replacements[$original] = \Drupal::service('date.formatter')->format($date, $name, '', NULL, $langcode);
+        continue;
+      }
       switch ($name) {
-        case 'short':
-        case 'medium':
-        case 'long':
-          $date_format = DateFormat::load($name);
-          $bubbleable_metadata->addCacheableDependency($date_format);
-          $replacements[$original] = \Drupal::service('date.formatter')->format($date, $name, '', NULL, $langcode);
-          break;
-
         case 'since':
           $replacements[$original] = \Drupal::service('date.formatter')->formatTimeDiffSince($date, ['langcode' => $langcode]);
           $bubbleable_metadata->setCacheMaxAge(0);
diff --git a/core/modules/system/tests/src/Kernel/Token/TokenReplaceKernelTest.php b/core/modules/system/tests/src/Kernel/Token/TokenReplaceKernelTest.php
index 9e878f5112..3d41dfb45a 100644
--- a/core/modules/system/tests/src/Kernel/Token/TokenReplaceKernelTest.php
+++ b/core/modules/system/tests/src/Kernel/Token/TokenReplaceKernelTest.php
@@ -5,7 +5,10 @@
 use Drupal\Component\Render\FormattableMarkup;
 use Drupal\Component\Utility\Html;
 use Drupal\Component\Utility\Xss;
+use Drupal\Core\Datetime\Entity\DateFormat;
 use Drupal\Core\Render\BubbleableMetadata;
+use mysql_xdevapi\Exception;
+use phpDocumentor\Reflection\DocBlock\Tags\Example;
 
 /**
  * Generates text using placeholders for dummy content to check token
@@ -136,10 +139,20 @@ public function testSystemDateTokenReplacement() {
 
     // Generate and test tokens.
     $tests = [];
+    /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
     $date_formatter = \Drupal::service('date.formatter');
-    $tests['[date:short]'] = $date_formatter->format($date, 'short', '', NULL, $this->interfaceLanguage->getId());
-    $tests['[date:medium]'] = $date_formatter->format($date, 'medium', '', NULL, $this->interfaceLanguage->getId());
-    $tests['[date:long]'] = $date_formatter->format($date, 'long', '', NULL, $this->interfaceLanguage->getId());
+
+    // Test standard date format tokens.
+    $date_formats = array_keys(\Drupal::entityTypeManager()->getStorage('date_format')->loadMultiple());
+    $this->assertCount(11, $date_formats);
+    $this->assertTrue(in_array('short', $date_formats));
+    $this->assertTrue(in_array('medium', $date_formats));
+    $this->assertTrue(in_array('long', $date_formats));
+    $this->assertTrue(in_array('html_date', $date_formats));
+    foreach ($date_formats as $date_format) {
+      $tests['[date:' . $date_format . ']'] = $date_formatter->format($date, $date_format, '', NULL, $this->interfaceLanguage->getId());
+    }
+
     $tests['[date:custom:m/j/Y]'] = $date_formatter->format($date, 'custom', 'm/j/Y', NULL, $this->interfaceLanguage->getId());
     $tests['[date:since]'] = $date_formatter->formatTimeDiffSince($date, ['langcode' => $this->interfaceLanguage->getId()]);
     $tests['[date:raw]'] = Xss::filter($date);
@@ -153,4 +166,30 @@ public function testSystemDateTokenReplacement() {
     }
   }
 
+  /**
+   * Tests the generation of all system date format tokens when formats change.
+   */
+  public function testSystemDateTokenGetInfo() {
+    $tokens = \Drupal::token()->getInfo();
+    $this->assertArrayNotHasKey('y2k', $tokens['tokens']['date']);
+
+    // Add new tokens.
+    $date_format = DateFormat::create([
+      'id' => 'y2k',
+      'label' => 'Y2K',
+      'pattern' => 'y',
+    ]);
+    $date_format->save();
+
+    $tokens = \Drupal::token()->getInfo();
+    $this->assertArrayHasKey('y2k', $tokens['tokens']['date']);
+
+    // Delete new token.
+    DateFormat::load('y2k')->delete();
+
+    // Get the count of removed tokens.
+    $tokens = \Drupal::token()->getInfo();
+    $this->assertArrayNotHasKey('y2k', $tokens['tokens']['date']);
+  }
+
 }
