Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.197
diff -u -p -r1.197 system.admin.inc
--- modules/system/system.admin.inc	26 Aug 2009 10:53:45 -0000	1.197
+++ modules/system/system.admin.inc	5 Sep 2009 15:02:46 -0000
@@ -1588,7 +1588,7 @@ function system_rss_feeds_settings() {
 }
 
 /**
- * Form builder; Configure the site date and time settings.
+ * Form builder; Configure the site regional settings.
  *
  * @ingroup forms
  * @see system_settings_form()
@@ -1596,7 +1596,7 @@ function system_rss_feeds_settings() {
  */
 function system_regional_settings() {
   drupal_add_js(drupal_get_path('module', 'system') . '/system.js');
-  drupal_add_js(array('dateTime' => array('lookup' => url('admin/config/regional/settings/lookup'))), 'setting');
+  drupal_add_js(array('dateTime' => array('lookup' => url('admin/config/regional/date-time/formats/lookup'))), 'setting');
 
   include_once DRUPAL_ROOT . '/includes/locale.inc';
   $countries = country_get_list();
@@ -1606,31 +1606,6 @@ function system_regional_settings() {
   // Date settings:
   $zones = system_time_zones();
 
-  // Date settings: possible date formats
-  $date_short = array('Y-m-d H:i', 'm/d/Y - H:i', 'd/m/Y - H:i', 'Y/m/d - H:i',
-           'd.m.Y - H:i', 'm/d/Y - g:ia', 'd/m/Y - g:ia', 'Y/m/d - g:ia',
-           'M j Y - H:i', 'j M Y - H:i', 'Y M j - H:i',
-           'M j Y - g:ia', 'j M Y - g:ia', 'Y M j - g:ia');
-  $date_medium = array('D, Y-m-d H:i', 'D, m/d/Y - H:i', 'D, d/m/Y - H:i',
-          'D, Y/m/d - H:i', 'F j, Y - H:i', 'j F, Y - H:i', 'Y, F j - H:i',
-          'D, m/d/Y - g:ia', 'D, d/m/Y - g:ia', 'D, Y/m/d - g:ia',
-          'F j, Y - g:ia', 'j F Y - g:ia', 'Y, F j - g:ia', 'j. F Y - G:i');
-  $date_long = array('l, F j, Y - H:i', 'l, j F, Y - H:i', 'l, Y, F j - H:i',
-        'l, F j, Y - g:ia', 'l, j F Y - g:ia', 'l, Y, F j - g:ia', 'l, j. F Y - G:i');
-
-  // Date settings: construct choices for user
-  foreach ($date_short as $f) {
-    $date_short_choices[$f] = format_date(REQUEST_TIME, 'custom', $f);
-  }
-  foreach ($date_medium as $f) {
-    $date_medium_choices[$f] = format_date(REQUEST_TIME, 'custom', $f);
-  }
-  foreach ($date_long as $f) {
-    $date_long_choices[$f] = format_date(REQUEST_TIME, 'custom', $f);
-  }
-
-  $date_long_choices['custom'] = $date_medium_choices['custom'] = $date_short_choices['custom'] = t('Custom format');
-
   $form['locale'] = array(
     '#type' => 'fieldset',
     '#title' => t('Locale'),
@@ -1695,77 +1670,6 @@ function system_regional_settings() {
     '#description' => t('Only applied if users may set their own time zone.')
   );
 
-  $form['date_formats'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Date formats'),
-  );
-
-  $date_format_short = variable_get('date_format_short', $date_short[1]);
-  $form['date_formats']['date_format_short'] = array(
-    '#prefix' => '<div class="date-container"><div class="select-container">',
-    '#suffix' => '</div>',
-    '#type' => 'select',
-    '#title' => t('Short date format'),
-    '#attributes' => array('class' => array('date-format')),
-    '#default_value' => (isset($date_short_choices[$date_format_short]) ? $date_format_short : 'custom'),
-    '#options' => $date_short_choices,
-  );
-
-  $default_short_custom = variable_get('date_format_short_custom', (isset($date_short_choices[$date_format_short]) ? $date_format_short : ''));
-  $form['date_formats']['date_format_short_custom'] = array(
-    '#prefix' => '<div class="custom-container">',
-    '#suffix' => '</div></div>',
-    '#type' => 'textfield',
-    '#title' => t('Custom short date format'),
-    '#attributes' => array('class' => array('custom-format')),
-    '#default_value' => $default_short_custom,
-    '#description' => t('A user-defined short date format. See the <a href="@url">PHP manual</a> for available options. This format is currently set to display as <span>%date</span>.', array('@url' => 'http://php.net/manual/function.date.php', '%date' => format_date(REQUEST_TIME, 'custom', $default_short_custom))),
-  );
-
-  $date_format_medium = variable_get('date_format_medium', $date_medium[1]);
-  $form['date_formats']['date_format_medium'] = array(
-    '#prefix' => '<div class="date-container"><div class="select-container">',
-    '#suffix' => '</div>',
-    '#type' => 'select',
-    '#title' => t('Medium date format'),
-    '#attributes' => array('class' => array('date-format')),
-    '#default_value' => (isset($date_medium_choices[$date_format_medium]) ? $date_format_medium : 'custom'),
-    '#options' => $date_medium_choices,
-  );
-
-  $default_medium_custom = variable_get('date_format_medium_custom', (isset($date_medium_choices[$date_format_medium]) ? $date_format_medium : ''));
-  $form['date_formats']['date_format_medium_custom'] = array(
-    '#prefix' => '<div class="custom-container">',
-    '#suffix' => '</div></div>',
-    '#type' => 'textfield',
-    '#title' => t('Custom medium date format'),
-    '#attributes' => array('class' => array('custom-format')),
-    '#default_value' => $default_medium_custom,
-    '#description' => t('A user-defined medium date format. See the <a href="@url">PHP manual</a> for available options. This format is currently set to display as <span>%date</span>.', array('@url' => 'http://php.net/manual/function.date.php', '%date' => format_date(REQUEST_TIME, 'custom', $default_medium_custom))),
-  );
-
-  $date_format_long = variable_get('date_format_long', $date_long[0]);
-  $form['date_formats']['date_format_long'] = array(
-    '#prefix' => '<div class="date-container"><div class="select-container">',
-    '#suffix' => '</div>',
-    '#type' => 'select',
-    '#title' => t('Long date format'),
-    '#attributes' => array('class' => array('date-format')),
-    '#default_value' => (isset($date_long_choices[$date_format_long]) ? $date_format_long : 'custom'),
-    '#options' => $date_long_choices,
-  );
-
-  $default_long_custom = variable_get('date_format_long_custom', (isset($date_long_choices[$date_format_long]) ? $date_format_long : ''));
-  $form['date_formats']['date_format_long_custom'] = array(
-    '#prefix' => '<div class="custom-container">',
-    '#suffix' => '</div></div>',
-    '#type' => 'textfield',
-    '#title' => t('Custom long date format'),
-    '#attributes' => array('class' => array('custom-format')),
-    '#default_value' => $default_long_custom,
-    '#description' => t('A user-defined long date format. See the <a href="@url">PHP manual</a> for available options. This format is currently set to display as <span>%date</span>.', array('@url' => 'http://php.net/manual/function.date.php', '%date' => format_date(REQUEST_TIME, 'custom', $default_long_custom))),
-  );
-
   $form = system_settings_form($form, FALSE);
   // We will call system_settings_form_submit() manually, so remove it for now.
   unset($form['#submit']);
@@ -1789,6 +1693,162 @@ function system_regional_settings_submit
 }
 
 /**
+ * Form builder; Configure the site date and time settings.
+ *
+ * @ingroup forms
+ * @see system_settings_form()
+ * @see system_date_time_settings_submit()
+ */
+function system_date_time_settings() {
+  drupal_add_js(drupal_get_path('module', 'system') . '/system.js');
+  drupal_add_js(array('dateTime' => array('lookup' => url('admin/config/regional/date-time/formats/lookup'))), 'setting');
+
+  // Get list of all available date types.
+  $format_types = system_get_date_types('', TRUE);
+
+  // Get list of all available date formats.
+  $all_formats = array();
+  $date_formats = system_get_date_formats('', TRUE); // Call this to rebuild the list, and to have default list.
+  foreach ($date_formats as $type => $format_info) {
+    $all_formats = array_merge($all_formats, $format_info);
+  }
+  $custom_formats = system_get_date_formats('custom');
+  if (!empty($format_types)) {
+    foreach ($format_types as $type => $type_info) {
+      // If a system type, only show the available formats for that type and
+      // custom ones.
+      if ($type_info['locked'] == 1) {
+        $formats = system_get_date_formats($type);
+        if (empty($formats)) {
+          $formats = $all_formats;
+        }
+        elseif (!empty($custom_formats)) {
+          $formats = array_merge($formats, $custom_formats);
+        }
+      }
+      // If a user configured type, show all available date formats.
+      else {
+        $formats = $all_formats;
+      }
+
+      $choices = array();
+      foreach ($formats as $f => $format) {
+        $choices[$f] = format_date(REQUEST_TIME, 'custom', $f);
+      }
+      $default = variable_get('date_format_' . $type, array_shift(array_keys($formats)));
+
+      // Get date type info for this date type.
+      $type_info = system_get_date_types($type);
+
+      // Show date format select list.
+      $form['date_format_' . $type] = array(
+        '#prefix' => '<div class="date-container"><div class="select-container">',
+        // Leave the date-container div open if we are going to be adding to and
+        // then closing it below.
+        '#suffix' => ($type_info['locked'] == 0) ? '</div>' : '</div></div>',
+        '#type' => 'select',
+        '#title' => t('!type date format', array('!type' => $type_info['title'])),
+        '#attributes' => array('class' => array('date-format')),
+        '#default_value' => (isset($choices[$default]) ? $default : 'custom'),
+        '#options' => $choices,
+      );
+
+      // If this isn't a system provided type, allow the user to remove it from
+      // the system.
+      if ($type_info['locked'] == 0) {
+        $form['date_format_' . $type . '_delete'] = array(
+          '#prefix' => '<div class="date-format-delete">',
+          '#suffix' => '</div></div>',
+          '#markup' => l(t('delete'), 'admin/config/regional/date-time/types/delete/' . $type),
+        );
+      }
+    }
+  }
+
+  // Display a message if no date types configured.
+  $form['#empty_text'] = t('No date types available. <a href="@link">Add date type</a>.', array('@link' => url('admin/config/regional/date-time/types/add')));
+
+  $form = system_settings_form($form, FALSE);
+  // We will call system_settings_form_submit() manually, so remove it for now.
+  unset($form['#submit']);
+  return $form;
+}
+
+/**
+ * Process system_date_time_settings form submissions.
+ */
+function system_date_time_settings_submit($form, &$form_state) {
+  return system_settings_form_submit($form, $form_state);
+}
+
+/**
+ * Add new date type.
+ *
+ * @ingroup forms
+ * @ingroup system_add_date_format_type_form_validate()
+ * @ingroup system_add_date_format_type_form_submit()
+ */
+function system_add_date_format_type_form() {
+  $form['add_date_format_title'] = array(
+    '#title' => t('Name'),
+    '#description' => t('The human-readable name for this date type.'),
+    '#type' => 'textfield',
+    '#size' => 20,
+    '#prefix' => '<div class="date-container"><div class="date-format-name">',
+    '#suffix' => '</div>',
+  );
+
+  $form['add_date_format_type'] = array(
+    '#title' => t('Type'),
+    '#description' => t('The machine-readable name of this date type. <br>This name must contain only lowercase letters, numbers, and underscores and must be unique.'),
+    '#type' => 'textfield',
+    '#size' => 20,
+    '#prefix' => '<div class="date-format-type">',
+    '#suffix' => '</div></div>',
+  );
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save'),
+  );
+
+  $form['#validate'][] = 'system_add_date_format_type_form_validate';
+  $form['#submit'][] = 'system_add_date_format_type_form_submit';
+
+  return $form;
+}
+
+/**
+ * Validate system_add_date_format_type form submissions.
+ */
+function system_add_date_format_type_form_validate($form, &$form_state) {
+  if (!empty($form_state['values']['add_date_format_type']) && !empty($form_state['values']['add_date_format_title'])) {
+    if (!preg_match("/^[a-zA-Z0-9_]+$/", $form_state['values']['add_date_format_type'])) {
+      form_set_error('add_date_format_type', t('The date type must contain only alphanumeric characters and underscores.'));
+    }
+    $types = system_get_date_types();
+    if (in_array($form_state['values']['add_date_format_type'], array_keys($types))) {
+      form_set_error('add_date_format_type', t('This date type already exists.  Please enter a unique type.'));
+    }
+  }
+}
+
+/**
+ * Process system_add_date_format_type form submissions.
+ */
+function system_add_date_format_type_form_submit($form, &$form_state) {
+  include_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'system') . '/' . 'system.date.inc';
+  $format_type = array();
+  $format_type['title'] = $form_state['values']['add_date_format_title'];
+  $format_type['type'] = $form_state['values']['add_date_format_type'];
+  $format_type['locked'] = 0;
+  $format_type['is_new'] = 1;
+  system_date_format_type_save($format_type);
+  drupal_set_message(t('New date type added successfully.'));
+  $form_state['redirect'] = 'admin/config/regional/date-time';
+}
+
+/**
  * Return the date for a given format string via Ajax.
  */
 function system_date_time_lookup() {
@@ -2294,3 +2354,154 @@ function theme_system_themes_form($form)
   $output .= drupal_render_children($form);
   return $output;
 }
+
+/**
+ * Menu callback; present a form for deleting a date format.
+ */
+function system_date_delete_format_form(&$form_state, $dfid) {
+  $form = array();
+  $form['dfid'] = array(
+    '#type' => 'value',
+    '#value' => $dfid,
+  );
+  $format = system_get_date_format($dfid);
+
+  $output = confirm_form($form,
+    t('Are you sure you want to remove the format %format?', array('%format' => format_date(REQUEST_TIME, 'custom', $format->format))),
+    'admin/config/regional/date-time/formats',
+    t('This action cannot be undone.'),
+    t('Remove'), t('Cancel'),
+    'confirm'
+  );
+
+  return $output;
+}
+
+/**
+ * Delete a configured date format.
+ */
+function system_date_delete_format_form_submit($form, &$form_state) {
+  include_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'system') . '/' . 'system.date.inc';
+  if ($form_state['values']['confirm']) {
+    $format = system_get_date_format($form_state['values']['dfid']);
+    system_date_format_delete($form_state['values']['dfid']);
+    drupal_set_message(t('Removed date format %format.', array('%format' => format_date(REQUEST_TIME, 'custom', $format->format))));
+    $form_state['redirect'] = 'admin/config/regional/date-time/formats';
+  }
+}
+
+/**
+ * Menu callback; present a form for deleting a date type.
+ */
+function system_delete_date_format_type_form(&$form_state, $format_type) {
+  $form = array();
+  $form['format_type'] = array(
+    '#type' => 'value',
+    '#value' => $format_type,
+  );
+  $type_info = system_get_date_types($format_type);
+
+  $output = confirm_form($form,
+    t('Are you sure you want to remove the date type %type?', array('%type' => $type_info['title'])),
+    'admin/config/regional/date-time',
+    t('This action cannot be undone.'),
+    t('Remove'), t('Cancel'),
+    'confirm'
+  );
+
+  return $output;
+}
+
+/**
+ * Delete a configured date type.
+ */
+function system_delete_date_format_type_form_submit($form, &$form_state) {
+  include_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'system') . '/' . 'system.date.inc';
+  if ($form_state['values']['confirm']) {
+    $type_info = system_get_date_types($form_state['values']['format_type']);
+    system_date_format_type_delete($form_state['values']['format_type']);
+    drupal_set_message(t('Removed date type %type.', array('%type' => $type_info['title'])));
+    $form_state['redirect'] = 'admin/config/regional/date-time';
+  }
+}
+
+
+/**
+ * Displays the date format strings overview page.
+ */
+function system_date_time_formats() {
+  $header = array(t('Format'), t('Operations'));
+  $rows = array();
+
+  $formats = system_get_date_formats('custom', TRUE);
+  if (!empty($formats)) {
+    foreach ($formats as $format) {
+      $row = array();
+      $row[] = array('data' => format_date(REQUEST_TIME, 'custom', $format['format']));
+      $row[] = array('data' => l(t('delete'), 'admin/config/regional/date-time/formats/delete/' . $format['dfid']));
+      $rows[] = $row;
+    }
+  }
+
+  if (empty($rows)) {
+    $rows[] = array(array('data' => t('No custom date formats available. <a href="@link">Add date format</a>.', array('@link' => url('admin/config/regional/date-time/formats/add'))), 'colspan' => '5', 'class' => array('message')));
+  }
+
+  $build['date_formats_table'] = array(
+    '#theme' => 'table',
+    '#header' => $header,
+    '#rows' => $rows
+  );
+
+  return $build;
+}
+
+/**
+ * Allow users to add additional date formats.
+ */
+function system_add_date_formats_form() {
+  drupal_add_js(drupal_get_path('module', 'system') . '/system.js');
+  drupal_add_js(array('dateTime' => array('lookup' => url('admin/config/regional/date-time/formats/lookup'))), 'setting');
+
+  $form['add_date_format'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Format string'),
+    '#attributes' => array('class' => array('custom-format')),
+    '#description' => t('A user-defined date format. See the <a href="@url">PHP manual</a> for available options. This format is currently set to display as <span>%date</span>.', array('@url' => 'http://php.net/manual/function.date.php', '%date' => format_date(REQUEST_TIME, 'custom', '-'))),
+  );
+
+  $form['update'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save configuration'),
+  );
+
+  $form['#validate'][] = 'system_add_date_formats_form_validate';
+  $form['#submit'][] = 'system_add_date_formats_form_submit';
+
+  return $form;
+}
+
+/**
+ * Validate new date format string submission.
+ */
+function system_add_date_formats_form_validate($form, &$form_state) {
+  $formats = system_get_date_formats('custom');
+  if (!empty($formats) && in_array(trim($form_state['values']['add_date_format']), array_keys($formats))) {
+    form_set_error('add_date_format', t('This format already exists.  Please enter a unique format string.'));
+  }
+}
+
+/**
+ * Process new date format string submission.
+ */
+function system_add_date_formats_form_submit($form, &$form_state) {
+  $format = array();
+  $format['format'] = trim($form_state['values']['add_date_format']);
+  $format['type'] = 'custom';
+  $format['locked'] = 0;
+  $format['is_new'] = 1;
+  system_date_format_save($format);
+
+  $form_state['redirect'] = 'admin/config/regional/date-time/formats';
+  drupal_set_message(t('Configuration saved.'));
+}
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.384
diff -u -p -r1.384 system.install
--- modules/system/system.install	5 Sep 2009 13:05:31 -0000	1.384
+++ modules/system/system.install	5 Sep 2009 15:02:46 -0000
@@ -688,6 +688,90 @@ function system_schema() {
   $schema['cache_registry'] = $schema['cache'];
   $schema['cache_registry']['description'] = 'Cache table for the code registry system to remember what code files need to be loaded on any given page.';
 
+  $schema['date_format_types'] = array(
+    'description' => 'For storing configured date format types.',
+    'fields' => array(
+      'type' => array(
+        'description' => 'The date format type, e.g. medium.',
+        'type' => 'varchar',
+        'length' => 200,
+        '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'),
+  );
+
+  $schema['date_formats'] = array(
+    'description' => 'For storing 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' => 200,
+        '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' => 'For storing 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' => 200,
+        'not null' => TRUE,
+      ),
+      'language' => array(
+        'description' => 'A {languages}.language for this format to be used with.',
+        'type' => 'varchar',
+        'length' => 12,
+        'not null' => TRUE,
+      ),
+    ),
+    'primary key' => array('type', 'language'),
+  );
+
   $schema['file'] = array(
     'description' => 'Stores information for uploaded files.',
     'fields' => array(
@@ -2469,6 +2553,103 @@ function system_update_7037() {
 }
 
 /**
+ * Create new date format tables.
+ */
+function system_update_7038() {
+  $ret = array();
+
+  $schema['date_format_types'] = array(
+    'description' => 'For storing configured date format types.',
+    'fields' => array(
+      'type' => array(
+        'description' => 'The date format type, e.g. medium.',
+        'type' => 'varchar',
+        'length' => 200,
+        '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'),
+  );
+
+  $schema['date_formats'] = array(
+    'description' => 'For storing 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' => 200,
+        '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' => 'For storing 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' => 200,
+        'not null' => TRUE,
+      ),
+      'language' => array(
+        'description' => 'A {languages}.language for this format to be used with.',
+        'type' => 'varchar',
+        'length' => 12,
+        'not null' => TRUE,
+      ),
+    ),
+    'primary key' => array('type', 'language'),
+  );
+
+  db_create_table($ret, 'date_format_types', $schema['date_format_types']);
+  db_create_table($ret, 'date_formats', $schema['date_formats']);
+  db_create_table($ret, 'date_format_locale', $schema['date_format_locale']);
+
+  return $ret;
+}
+
+/**
  * @} End of "defgroup updates-6.x-to-7.x"
  * The next series of updates should start at 8000.
  */
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.784
diff -u -p -r1.784 system.module
--- modules/system/system.module	1 Sep 2009 16:50:12 -0000	1.784
+++ modules/system/system.module	5 Sep 2009 15:02:47 -0000
@@ -809,6 +809,8 @@ function system_menu() {
     'access arguments' => array('administer site configuration'),
     'file' => 'system.admin.inc',
   );
+
+  // Regional and date settings.
   $items['admin/config/regional'] = array(
     'title' => 'Regional and language',
     'description' => 'Regional settings, localization and translation.',
@@ -820,20 +822,87 @@ function system_menu() {
   );
   $items['admin/config/regional/settings'] = array(
     'title' => 'Regional settings',
-    'description' => "Settings for how Drupal displays date and time, as well as the system's default time zone.",
+    'description' => "Settings for the site's default time zone and country settings.",
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_regional_settings'),
     'access arguments' => array('administer site configuration'),
     'weight' => -10,
     'file' => 'system.admin.inc',
   );
-  $items['admin/config/regional/settings/lookup'] = array(
+  $items['admin/config/regional/date-time'] = array(
+    'title' => 'Date and time',
+    'description' => "Configure display formats for date and time.",
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('system_date_time_settings'),
+    'access arguments' => array('administer site configuration'),
+    'weight' => -9,
+    'file' => 'system.admin.inc',
+  );
+  $items['admin/config/regional/date-time/types'] = array(
+    'title' => 'Types',
+    'description' => "Configure display formats for date and time.",
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('system_date_time_settings'),
+    'access arguments' => array('administer site configuration'),
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'weight' => -10,
+    'file' => 'system.admin.inc',
+  );
+  $items['admin/config/regional/date-time/types/add'] = array(
+    'title' => 'Add date type',
+    'description' => "Add new date type.",
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('system_add_date_format_type_form'),
+    'access arguments' => array('administer site configuration'),
+    'type' => MENU_LOCAL_ACTION,
+    'weight' => -10,
+    'file' => 'system.admin.inc',
+  );
+  $items['admin/config/regional/date-time/types/delete/%'] = array(
+    'title' => 'Delete date type',
+    'description' => 'Allow users to delete a configured date type.',
+    'type' => MENU_CALLBACK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('system_delete_date_format_type_form', 6),
+    'access arguments' => array('administer site configuration'),
+    'file' => 'system.admin.inc',
+  );
+  $items['admin/config/regional/date-time/formats'] = array(
+    'title' => 'Formats',
+    'description' => "Configure display format strings for date and time.",
+    'page callback' => 'system_date_time_formats',
+    'access arguments' => array('administer site configuration'),
+    'type' => MENU_LOCAL_TASK,
+    'weight' => -9,
+    'file' => 'system.admin.inc',
+  );
+  $items['admin/config/regional/date-time/formats/add'] = array(
+    'title' => 'Add format',
+    'description' => 'Allow users to add additional date formats.',
+    'type' => MENU_LOCAL_ACTION,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('system_add_date_formats_form'),
+    'access arguments' => array('administer site configuration'),
+    'weight' => -10,
+    'file' => 'system.admin.inc',
+  );
+  $items['admin/config/regional/date-time/formats/delete/%'] = array(
+    'title' => 'Delete date format',
+    'description' => 'Allow users to delete a configured date format.',
+    'type' => MENU_CALLBACK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('system_date_delete_format_form', 6),
+    'access arguments' => array('administer site configuration'),
+    'file' => 'system.admin.inc',
+  );
+  $items['admin/config/regional/date-time/formats/lookup'] = array(
     'title' => 'Date and time lookup',
     'type' => MENU_CALLBACK,
     'page callback' => 'system_date_time_lookup',
     'access arguments' => array('administer site configuration'),
     'file' => 'system.admin.inc',
   );
+
   $items['admin/config/search'] = array(
     'title' => 'Search and metadata',
     'description' => 'Local site search, metadata and SEO.',
@@ -2427,6 +2496,9 @@ function system_cron() {
   foreach ($cache_tables as $table) {
     cache_clear_all(NULL, $table);
   }
+  
+  // Rebuild list of date formats.
+  system_date_formats_rebuild();
 
   // Reset expired items in the default queue implementation table. If that's
   // not used, this will simply be a no-op.
@@ -3192,3 +3264,141 @@ function theme_system_run_cron_image($im
   return '<noscript><div id="system-cron-image">' . theme('image', $image_path, '', '', array(), FALSE) . '</div></noscript>';
 }
 
+/**
+ * Get the list of available date types and attributes.
+ *
+ * @param $type
+ *   The date type, e.g. 'short', 'medium', 'long', 'custom'.  If empty, then
+ *   all attributes for that type will be returned.
+ * @param $reset
+ *   Whether or not to reset this function's internal cache (defaults to FALSE).
+ * @return
+ *   Array of date types.
+ */
+function system_get_date_types($type = NULL, $reset = FALSE) {
+  static $_date_format_types;
+
+  if ($reset || !isset($_date_format_types)) {
+    include_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'system') . '/' . 'system.date.inc';
+    $_date_format_types = _system_date_format_types_build();
+  }
+
+  return $type ? (isset($_date_format_types[$type]) ? $_date_format_types[$type] : FALSE) : $_date_format_types;
+}
+
+/**
+ * Implements hook_date_format_types().
+ */
+function system_date_format_types() {
+  return array(
+    'long' => t('Long'),
+    'medium' => t('Medium'),
+    'short' => t('Short'),
+  );
+}
+
+/**
+ * Implements hook_date_formats().
+ *
+ * @return
+ *   An array of date formats with attributes 'type' (short, medium or long),
+ *   'format' (the format string) and 'locales'.  The 'locales' attribute is an
+ *   array of locales, which can include both 2 character language codes like
+ *   'en', 'fr', but also 5 character language codes like 'en-gb' and 'en-us'.
+ */
+function system_date_formats() {
+  include_once DRUPAL_ROOT . '/includes/date_formats.inc';
+  return system_default_date_formats();
+}
+
+/**
+ * Get the list of date formats for a particular format length.
+ *
+ * @param $type
+ *   The date type: 'short', 'medium', 'long', 'custom'.  If empty, then all
+ *   available types will be returned.
+ * @param $reset
+ *   Whether or not to reset this function's internal cache (defaults to FALSE).
+ * @return
+ *   Array of date formats.
+ */
+function system_get_date_formats($type = NULL, $reset = FALSE) {
+  static $_date_formats;
+
+  if ($reset || !isset($_date_formats)) {
+    include_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'system') . '/' . 'system.date.inc';
+    $_date_formats = _system_date_formats_build();
+  }
+
+  return $type ? (isset($_date_formats[$type]) ? $_date_formats[$type] : FALSE) : $_date_formats;
+}
+
+/**
+ * Get the format details for a particular id.
+ *
+ * @param $dfid
+ *   Identifier of a date format string.
+ * @return
+ *   Array of date format details.
+ */
+function system_get_date_format($dfid) {
+  $format = db_query('SELECT df.dfid, df.format, df.type, df.locked FROM {date_formats} df WHERE df.dfid = :dfid', array(':dfid' => $dfid))->fetch();
+  return $format;
+}
+
+/**
+ * Resets the database cache of date formats, and saves all new date formats to
+ * the database.
+ */
+function system_date_formats_rebuild() {
+  include_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'system') . '/' . 'system.date.inc';
+  $date_formats = system_get_date_formats(NULL, TRUE);
+
+  foreach ($date_formats as $format_type => $formats) {
+    foreach ($formats as $format => $info) {
+      system_date_format_save($info);
+    }
+  }
+
+  // Rebuild configured date formats locale list.
+  system_date_format_locale(NULL, NULL, TRUE);
+
+  _system_date_formats_build();
+}
+
+/**
+ * Get the appropriate date format for a type and locale.
+ *
+ * @param $langcode
+ *   Language code for the current locale.  This can be a 2 character language
+ *   code like 'en', 'fr', or a longer 5 character code like 'en-gb'.
+ * @param $type
+ *   Date type: short, medium, long, custom.
+ * @param $reset
+ *   Whether or not to reset this function's internal cache (defaults to FALSE).
+ * @return
+ *   The format string, or NULL if no matching format found.
+ */
+function system_date_format_locale($langcode = NULL, $type = NULL, $reset = FALSE) {
+  static $formats;
+
+  if ($reset || empty($formats)) {
+    $formats = array();
+    $result = db_query("SELECT format, type, language FROM {date_format_locale}");
+    foreach ($result as $record) {
+      if (!isset($formats[$record->language])) {
+        $formats[$record->language] = array();
+      }
+      $formats[$record->language][$record->type] = $record->format;
+    }
+  }
+
+  if ($type && $langcode && !empty($formats[$langcode][$type])) {
+    return $formats[$langcode][$type];
+  }
+  elseif ($langcode && !empty($formats[$langcode])) {
+    return $formats[$langcode];
+  }
+
+  return FALSE;
+}
