diff --git a/tests/token_test.module b/tests/token_test.module
index 1b2f9aa..36e32d8 100644
--- a/tests/token_test.module
+++ b/tests/token_test.module
@@ -12,3 +12,15 @@ function token_test_exit() {
     variable_set('token_page_tokens', $debug);
   }
 }
+
+/**
+ * Implements hook_date_format_types().
+ */
+function token_test_date_format_types() {
+  $info['token_test'] = t('Token test date format');
+
+  // Explicitly set the variable here as well.
+  variable_set('date_format_token_test', 'Y');
+
+  return $info;
+}
diff --git a/token.module b/token.module
index ad4107b..2f7813b 100644
--- a/token.module
+++ b/token.module
@@ -165,6 +165,10 @@ function token_form_alter(&$form, $form_state, $form_id) {
     case 'profile_field_delete':
     // User picture form.
     case 'user_admin_settings':
+    // System date type form.
+    // @todo Remove when http://drupal.org/node/1173706 is fixed.
+    case 'system_add_date_format_type_form':
+    case 'system_delete_date_format_type_form':
       $form += array('#submit' => array());
       array_unshift($form['#submit'], 'token_clear_cache');
       break;
diff --git a/token.test b/token.test
index 8bf7113..009b97b 100644
--- a/token.test
+++ b/token.test
@@ -836,3 +836,22 @@ class TokenRandomTestCase extends TokenTestHelper {
     }
   }
 }
+
+class TokenDateTestCase extends TokenTestHelper {
+  public static function getInfo() {
+    return array(
+      'name' => 'Date token tests',
+      'description' => 'Test the date tokens.',
+      'group' => 'Token',
+    );
+  }
+
+  function testDateTokens() {
+    $tokens = array(
+      'token_test' => '1984',
+      'invalid_format' => NULL,
+    );
+
+    $this->assertTokens('date', array('date' => 453859200), $tokens);
+  }
+}
diff --git a/token.tokens.inc b/token.tokens.inc
index 4cf14c9..19cac12 100644
--- a/token.tokens.inc
+++ b/token.tokens.inc
@@ -52,6 +52,19 @@ function token_token_info_alter(&$info) {
   $info['tokens']['term']['url']['type'] = 'url';
   $info['tokens']['user']['url']['type'] = 'url';
   // @todo Support other tokens not named 'url'
+
+  // Add support for custom date formats.
+  // @todo Remove when http://drupal.org/node/1173706 is fixed.
+  $date_format_types = system_get_date_types();
+  foreach ($date_format_types as $date_format_type => $date_format_type_info) {
+    if (!isset($info['tokens']['date'][$date_format_type])) {
+      $info['tokens']['date'][$date_format_type] = array(
+        'name' => $date_format_type_info['title'],
+        'description' => t("A date in '@type' format. (%date)", array('@type' => $date_format_type, '%date' => format_date(REQUEST_TIME, $date_format_type))),
+        'module' => 'token',
+      );
+    }
+  }
 }
 
 /**
@@ -315,6 +328,19 @@ function token_tokens($type, $tokens, array $data = array(), array $options = ar
 
   $sanitize = !empty($options['sanitize']);
 
+  // Date tokens.
+  if ($type == 'date') {
+    $date = !empty($data['date']) ? $data['date'] : REQUEST_TIME;
+
+    // @todo Remove when http://drupal.org/node/1173706 is fixed.
+    $date_format_types = system_get_date_types();
+    foreach ($tokens as $name => $original) {
+      if (isset($date_format_types[$name]) && _token_module('date', $name) == 'token') {
+        $replacements[$original] = format_date($date, $name, '', NULL, $language_code);
+      }
+    }
+  }
+
   // Current date tokens.
   // @todo Remove when http://drupal.org/node/943028 is fixed.
   if ($type == 'current-date') {
