diff --git a/includes/form.inc b/includes/form.inc
index 99570a5..6fc277e 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -501,22 +501,44 @@ function form_get_cache($form_build_id, &$form_state) {
 
 /**
  * Store a form in the cache.
+ *
+ * Besides a numeric value the expiration option accepts relative date formats
+ * like for php's strtotime, too.
+ * Using relative date formats enables you to set the cache expiration to a time
+ * independent from the time the cache is build.
+ * E.g. if you use 'tomorrow' as expiration time, the cache will expire next
+ * midnight independent if the cache was built 10am or 11:55pm.
+ *
+ * @see http://www.php.net/manual/en/datetime.formats.relative.php
+ *
  */
 function form_set_cache($form_build_id, $form, $form_state) {
-  // 6 hours cache life time for forms should be plenty.
-  $expire = 21600;
+  // Evaluate the cache lifetime.
+  if (!empty($form_state['cache_expire'])) {
+    $expire = $form_state['cache_expire'];
+  }
+  else {
+    $expire = variable_get('form_cache_expire', 21600);
+  }
+  // Allow relative date formats.
+  if (!is_numeric($expire)) {
+    $expire = strtotime($expire);
+  }
+  else {
+    $expire = REQUEST_TIME + $expire;
+  }
 
   // Cache form structure.
   if (isset($form)) {
     if ($GLOBALS['user']->uid) {
       $form['#cache_token'] = drupal_get_token();
     }
-    cache_set('form_' . $form_build_id, $form, 'cache_form', REQUEST_TIME + $expire);
+    cache_set('form_' . $form_build_id, $form, 'cache_form', $expire);
   }
 
   // Cache form state.
   if ($data = array_diff_key($form_state, array_flip(form_state_keys_no_cache()))) {
-    cache_set('form_state_' . $form_build_id, $data, 'cache_form', REQUEST_TIME + $expire);
+    cache_set('form_state_' . $form_build_id, $data, 'cache_form', $expire);
   }
 }
 
diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc
index 0d3a8d7..1675ad9 100644
--- a/modules/system/system.admin.inc
+++ b/modules/system/system.admin.inc
@@ -1673,6 +1673,33 @@ function system_performance_settings() {
     '#description' => t('The maximum time an external cache can use an old version of a page.')
   );
 
+  $form_cache_expire = variable_get('form_cache_expire', 21600);
+  $form['caching']['form_cache_expire'] = array(
+    '#type' => 'select',
+    '#title' => t('Expiration of cached forms'),
+    '#default_value' => $form_cache_expire,
+    '#options' => array('custom' => '<' . t('custom') . '>') + $period,
+    '#description' => t('The maximum time form and form_state are cached.')
+  );
+  $form_cache_expire_custom = (is_numeric($form_cache_expire)) ? REQUEST_TIME + $form_cache_expire : strtotime($form_cache_expire);
+  $form['caching']['form_cache_expire_custom'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Custom form cache expiration'),
+    '#default_value' => $form_cache_expire,
+    '#field_suffix' => t(
+      '%expire evaluates to %expiration_date',
+      array(
+        '%expire' => $form_cache_expire,
+        '%expiration_date' => date('Y/m/d - H:i:s', $form_cache_expire_custom),
+      )
+    ),
+    '#description' => t('Define a <a href="http://www.php.net/manual/en/datetime.formats.relative.php">relative date format</a> like for php\'s <a herf="http://php.net/manual/en/function.strtotime.php">strtotime</a>.'),
+    '#states' => array(
+      'visible' => array(':input[name="form_cache_expire"]' => array('value' => 'custom')),
+    ),
+    '#element_validate' => array('_system_performance_settings_validate_form_caching'),
+  );
+
   $directory = 'public://';
   $is_writable = is_dir($directory) && is_writable($directory);
   $disabled = !$is_writable;
@@ -1718,6 +1745,29 @@ function system_performance_settings() {
 }
 
 /**
+ * Validates the custom form expiration and stores it back into the used
+ * variable name
+ */
+function _system_performance_settings_validate_form_caching($element, &$form_state) {
+  if (!empty($element['#value']) && $form_state['values']['form_cache_expire'] == 'custom') {
+    $expire = $element['#value'];
+    if (!is_numeric($expire)) {
+      $expire = (int) strtotime($element['#value']);
+    }
+    else {
+      $expire += REQUEST_TIME;
+    }
+    if ($expire < REQUEST_TIME) {
+      form_error($element, t('The value of the custom form expiration evaluates to a time in the past. Please check the value.'));
+    }
+    else {
+      $form_state['values']['form_cache_expire'] = $element['#value'];
+    }
+  }
+  unset($form_state['values']['form_cache_expire_custom']);
+}
+
+/**
  * Submit callback; clear system caches.
  *
  * @ingroup forms
