diff --git modules/system/system.test modules/system/system.test
index 549df44..136c52a 100644
--- modules/system/system.test
+++ modules/system/system.test
@@ -923,6 +923,103 @@ class SiteMaintenanceTestCase extends DrupalWebTestCase {
 }
 
 /**
+ * Tests generic date format and date type functions and hooks
+ */
+class DateTimeUnitTest extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Date and time unit tests',
+      'description' => 'Performs tests on date format and date type functions and hooks.',
+      'group' => 'System',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('date_test');
+  }
+
+  /**
+   * Test that system_get_date_formats() returns module defined date formats.
+   */
+  function testSystemGetDateFormats() {
+    // Get a list of all known date formats.
+    $formats = system_get_date_formats();
+
+    // Verify the existence of the very short date format provided by the
+    // date_test module.
+    $very_short_format = $formats['date_test_very_short']['F Y'];
+    // In testing each date format, we unset the date format ID since we cannot
+    // know this value in advance.
+    unset($very_short_format['dfid']);
+    $expected_very_short_format = array(
+      'format' => 'F Y',
+      'type' => 'date_test_very_short',
+      'locales' => array(),
+      'locked' => TRUE,
+      'module' => 'date_test',
+      'is_new' => FALSE,
+    );
+    $this->assertEqual($very_short_format, $expected_very_short_format, t('Information about the %type date format %format was provided.', array('%type' => 'date_test_very_short', '%format' => 'F Y')));
+
+    // Verify the existence of the extra long date format provided by the
+    // date_test module. This format has been altered by
+    // hook_date_format_types_alter() and hook_date_formats_alter().
+    $extra_long_formats = system_get_date_formats('date_test_extra_long');
+    $extra_long_format = $extra_long_formats['l jS F Y h:i:sa'];
+    unset($extra_long_format['dfid']);
+    $expected_extra_long_format = array(
+      'format' => 'l jS F Y h:i:sa',
+      'type' => 'date_test_extra_long',
+      'locales' => array('en', 'en-us', 'en-ca'),
+      'locked' => TRUE,
+      'module' => 'date_test',
+      'is_new' => FALSE
+    );
+    $this->assertEqual($extra_long_format, $expected_extra_long_format, t('Information about the %type date format %format was provided.', array('%type' => 'date_test_extra_long', '%format' => 'l jS F Y h:i:sa')));
+
+    // This date format does not exist so the response should be FALSE.
+    $does_not_exist_formats = system_get_date_formats('does_not_exist');
+    $this->assertFalse($does_not_exist_formats, t('No information was date format information provided for a non-existent date type.'));
+  }
+
+  /**
+   * Test that system_get_date_types() returns module defined date types.
+   */
+  function testSystemGetDateTypes() {
+    // Get a list of all known date types.
+    $types = system_get_date_types();
+
+    // Verify the existence of the very short date type provided by the
+    // date_test module.
+    $expected_very_short_type = array(
+      'type' => 'date_test_very_short',
+      'title' => t('Date test very short'),
+      'locked' => TRUE,
+      'module' => 'date_test',
+      'is_new' => FALSE,
+    );
+    $this->assertEqual($types['date_test_very_short'], $expected_very_short_type, t('System provided %type date type found.', array('%type' => 'date_test_very_short')));
+
+    // Verify the existence of the extra long date type provided by the
+    // date_test module. This format has been altered by
+    // hook_date_format_types_alter().
+    $extra_long_type = system_get_date_types('date_test_extra_long');
+    $expected_extra_long_type = array(
+      'type' => 'date_test_extra_long',
+      'title' => t('Date test extra long'),
+      'locked' => TRUE,
+      'module' => 'date_test',
+      'is_new' => FALSE,
+    );
+    $this->assertEqual($extra_long_type, $expected_extra_long_type, t('System provided %type date type found.', array('%type' => 'date_test_extra_long')));
+
+    // This date type does not exist so the response should be FALSE.
+    $type_does_not_exist = system_get_date_types('does_not_exist');
+    $this->assertFalse($type_does_not_exist, t('No date type information provided for a non-existent date type.'));
+  }
+}
+
+/**
  * Tests generic date and time handling capabilities of Drupal.
  */
 class DateTimeFunctionalTest extends DrupalWebTestCase {
diff --git modules/system/tests/date_test.info modules/system/tests/date_test.info
new file mode 100644
index 0000000..35a5f36
--- /dev/null
+++ modules/system/tests/date_test.info
@@ -0,0 +1,7 @@
+; $Id$
+name = "System module date tests"
+description = "Support module for date testing."
+package = Testing
+version = VERSION
+core = 7.x
+hidden = TRUE
diff --git modules/system/tests/date_test.module modules/system/tests/date_test.module
new file mode 100644
index 0000000..caf4131
--- /dev/null
+++ modules/system/tests/date_test.module
@@ -0,0 +1,49 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Dummy module implementing date types and date formats for testing.
+ */
+
+/**
+ * Implements hook_date_format_types().
+ */
+function date_test_date_format_types() {
+  return array(
+    'date_test_very_short' => t('Date test very short'),
+    'date_test_extra_long' => t('Unknown'),
+  );
+}
+
+/**
+ * Implements hook_date_format_types_alter().
+ */
+function date_test_date_format_types_alter(&$types) {
+  $types['date_test_extra_long']['title'] = t('Date test extra long');
+}
+
+/*
+ * Implements hook_date_formats().
+ */
+function date_test_date_formats() {
+  return array(
+    array(
+      'type' => 'date_test_very_short',
+      'format' => 'F Y',
+      'locales' => array(),
+    ),
+    array(
+      'type' => 'date_test_extra_long',
+      'format' => 'l jS F Y h:i:sa',
+      'locales' => array('en', 'en-us'),
+    ),
+  );
+}
+
+/**
+ * Implements hook_date_formats_alter().
+ */
+function date_test_date_formats_alter(&$formats) {
+  $formats['date_test_extra_long']['l jS F Y h:i:sa']['locales'][] = 'en-ca';
+}
diff --git modules/system/system.module modules/system/system.module
index b5dfc54..2f0ca51 100644
--- modules/system/system.module
+++ modules/system/system.module
@@ -3524,9 +3524,10 @@ function system_date_formats() {
  *   - dfid: The date format ID.
  *   - format: The format string.
  *   - type: The machine-readable name of the date type.
- *   - locales: An array of language codes. This can include both 2 character
- *     language codes like 'en and 'fr' and 5 character language codes like
- *     'en-gb' and 'en-us'.
+ *   - locales: An array of locale codes, representing all the locales that
+ *     this format can apply to. This can include both 2 character language
+ *     codes like 'en and 'fr' and 5 character locale codes like 'en-gb' and
+ *     'en-us'. An empty array indicates the format is not locale-specific.
  *   - locked: A boolean indicating whether or not this date type should be
  *     configurable from the user interface.
  *   - module: The name of the module that defined this date format in its
@@ -3641,10 +3642,7 @@ function system_date_format_locale($langcode = NULL, $type = NULL) {
 function _system_date_format_types_build() {
   $types = array();
 
-  // Get list of modules that implement hook_date_format_types().
-  $modules = module_implements('date_format_types');
-
-  foreach ($modules as $module) {
+  foreach (module_implements('date_format_types') as $module) {
     $module_types = module_invoke($module, 'date_format_types');
     foreach ($module_types as $module_type => $type_title) {
       $type = array();
@@ -3693,12 +3691,13 @@ function _system_date_format_types_build() {
  *   - dfid: The date format ID.
  *   - format: The PHP date format string.
  *   - type: The machine-readable name of the date type the format belongs to.
- *   - locales: An array of language codes. This can include both 2 character
- *     language codes like 'en and 'fr' and 5 character language codes like
- *     'en-gb' and 'en-us'.
+ *   - locales: An array of locale codes, representing all the locales that
+ *     this format can apply to. This can include both 2 character language
+ *     codes like 'en and 'fr' and 5 character locale codes like 'en-gb' and
+ *     'en-us'. An empty array indicates the format is not locale-specific.
  *   - locked: A boolean indicating whether or not this date type should be
  *     configurable from the user interface.
- *   - module: The name of the module that defined this format in its
+ *   - module: The name of the module that defined this date format in its
  *     hook_date_formats(). An empty string if the format was user-defined.
  *   - is_new: A boolean indicating whether or not this date type is as of yet
  *     unsaved in the database.
@@ -3712,31 +3711,32 @@ function _system_date_formats_build() {
     system_date_format_type_save($info);
   }
 
-  // Get formats supplied by various contrib modules.
-  $module_formats = module_invoke_all('date_formats');
-
-  foreach ($module_formats as $module_format) {
-    // System types are locked.
-    $module_format['locked'] = 1;
-    // If no date type is specified, assign 'custom'.
-    if (!isset($module_format['type'])) {
-      $module_format['type'] = 'custom';
-    }
-    if (!in_array($module_format['type'], array_keys($types))) {
-      continue;
-    }
-    if (!isset($date_formats[$module_format['type']])) {
-      $date_formats[$module_format['type']] = array();
-    }
+  foreach (module_implements('date_formats') as $module) {
+    $module_formats = module_invoke($module, 'date_formats');
+    foreach ($module_formats as $module_format) {
+      $module_format['module'] = $module;
+      // System types are locked.
+      $module_format['locked'] = 1;
+      // If no date type is specified, assign 'custom'.
+      if (!isset($module_format['type'])) {
+        $module_format['type'] = 'custom';
+      }
+      if (!in_array($module_format['type'], array_keys($types))) {
+        continue;
+      }
+      if (!isset($date_formats[$module_format['type']])) {
+        $date_formats[$module_format['type']] = array();
+      }
 
-    // If another module already set this format, merge in the new settings.
-    if (isset($date_formats[$module_format['type']][$module_format['format']])) {
-      $date_formats[$module_format['type']][$module_format['format']] = array_merge_recursive($date_formats[$module_format['type']][$module_format['format']], $module_format);
-    }
-    else {
-      // This setting will be overridden later if it already exists in the db.
-      $module_format['is_new'] = TRUE;
-      $date_formats[$module_format['type']][$module_format['format']] = $module_format;
+      // If another module already set this format, merge in the new settings.
+      if (isset($date_formats[$module_format['type']][$module_format['format']])) {
+        $date_formats[$module_format['type']][$module_format['format']] = array_merge_recursive($date_formats[$module_format['type']][$module_format['format']], $module_format);
+      }
+      else {
+        // This setting will be overridden later if it already exists in the db.
+        $module_format['is_new'] = TRUE;
+        $date_formats[$module_format['type']][$module_format['format']] = $module_format;
+      }
     }
   }
 
@@ -3748,6 +3748,8 @@ function _system_date_formats_build() {
       $date_formats[$record->type] = array();
     }
     $format = (array) $record;
+    // The language is later saved as an element of the locales field.
+    unset($format['language']);
     $format['is_new'] = FALSE; // It's in the db, so override this setting.
     // If this format not already present, add it to the array.
     if (!isset($date_formats[$record->type][$record->format])) {
