diff --git a/core/includes/common.inc b/core/includes/common.inc
index 722c1f6..f8558f6 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -7071,6 +7071,7 @@ function drupal_parse_info_file($filename) {
     else {
       $data = file_get_contents($filename);
       $info[$filename] = drupal_parse_info_format($data);
+      $info[$filename]['mtime'] = filemtime($filename);
     }
   }
   return $info[$filename];
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index 97a4673..45c43d0 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -919,6 +919,183 @@ function system_modules($form, $form_state = array()) {
 }
 
 /**
+ * Menu callback; provides module enable/disable interface.
+ *
+ * The list of modules gets populated by module.info files, which contain each
+ * module's name, description, and information about which modules it requires.
+ * See drupal_parse_info_file() for information on module.info descriptors.
+ *
+ * Dependency checking is performed to ensure that a module:
+ * - can not be enabled if there are disabled modules it requires.
+ * - can not be disabled if there are enabled modules which depend on it.
+ *
+ * @param $form_state
+ *   An associative array containing the current state of the form.
+ *
+ * @return
+ *   The form array.
+ *
+ * @ingroup forms
+ * @see theme_system_modules()
+ * @see system_modules_submit()
+ */
+function system_modules_recent($form, $form_state = array()) {
+  // Get current list of modules.
+  $files = system_rebuild_module_data();
+
+  // Remove hidden modules from display list.
+  $visible_files = $files;
+  foreach ($visible_files as $filename => $file) {
+    if (!empty($file->info['hidden'])) {
+      unset($visible_files[$filename]);
+    }
+  }
+
+  uasort($visible_files, 'system_sort_modules_by_info_mtime');
+
+  // If the modules form was submitted, then system_modules_submit() runs first
+  // and if there are unfilled required modules, then $form_state['storage'] is
+  // filled, triggering a rebuild. In this case we need to display a
+  // confirmation form.
+  if (!empty($form_state['storage'])) {
+    return system_modules_confirm_form($visible_files, $form_state['storage']);
+  }
+
+  $modules = array();
+  $form['modules'] = array('#tree' => TRUE);
+
+  // Used when checking if module implements a help page.
+  $help_arg = module_exists('help') ? drupal_help_arg() : FALSE;
+
+  // Used when displaying modules that are required by the install profile.
+  require_once DRUPAL_ROOT . '/core/includes/install.inc';
+  $distribution_name = check_plain(drupal_install_profile_distribution_name());
+
+  // Iterate through each of the modules.
+  foreach ($visible_files as $filename => $module) {
+    $extra = array();
+    $extra['enabled'] = (bool) $module->status;
+    if (!empty($module->info['required'] )) {
+      $extra['disabled'] = TRUE;
+      $extra['required_by'][] = $distribution_name . (!empty($module->info['explanation']) ? ' ('. $module->info['explanation'] .')' : '');
+    }
+
+    // If this module requires other modules, add them to the array.
+    foreach ($module->requires as $requires => $v) {
+      if (!isset($files[$requires])) {
+        $extra['requires'][$requires] = t('@module (<span class="admin-missing">missing</span>)', array('@module' => drupal_ucfirst($requires)));
+        $extra['disabled'] = TRUE;
+      }
+      // Only display visible modules.
+      elseif (isset($visible_files[$requires])) {
+        $requires_name = $files[$requires]->info['name'];
+        // Disable this module if it is incompatible with the dependency's version.
+        if ($incompatible_version = drupal_check_incompatibility($v, str_replace(DRUPAL_CORE_COMPATIBILITY . '-', '', $files[$requires]->info['version']))) {
+          $extra['requires'][$requires] = t('@module (<span class="admin-missing">incompatible with</span> version @version)', array(
+            '@module' => $requires_name . $incompatible_version,
+            '@version' => $files[$requires]->info['version'],
+          ));
+          $extra['disabled'] = TRUE;
+        }
+        // Disable this module if the dependency is incompatible with this
+        // version of Drupal core.
+        elseif ($files[$requires]->info['core'] != DRUPAL_CORE_COMPATIBILITY) {
+          $extra['requires'][$requires] = t('@module (<span class="admin-missing">incompatible with</span> this version of Drupal core)', array(
+            '@module' => $requires_name,
+          ));
+          $extra['disabled'] = TRUE;
+        }
+        elseif ($files[$requires]->status) {
+          $extra['requires'][$requires] = t('@module (<span class="admin-enabled">enabled</span>)', array('@module' => $requires_name));
+        }
+        else {
+          $extra['requires'][$requires] = t('@module (<span class="admin-disabled">disabled</span>)', array('@module' => $requires_name));
+        }
+      }
+    }
+    // Generate link for module's help page, if there is one.
+    if ($help_arg && $module->status && in_array($filename, module_implements('help'))) {
+      if (module_invoke($filename, 'help', "admin/help#$filename", $help_arg)) {
+        $extra['links']['help'] = array(
+          '#type' => 'link',
+          '#title' => t('Help'),
+          '#href' => "admin/help/$filename",
+          '#options' => array('attributes' => array('class' =>  array('module-link', 'module-link-help'), 'title' => t('Help'))),
+        );
+      }
+    }
+    // Generate link for module's permission, if the user has access to it.
+    if ($module->status && user_access('administer permissions') && in_array($filename, module_implements('permission'))) {
+      $extra['links']['permissions'] = array(
+        '#type' => 'link',
+        '#title' => t('Permissions'),
+        '#href' => 'admin/people/permissions',
+        '#options' => array('fragment' => 'module-' . $filename, 'attributes' => array('class' => array('module-link', 'module-link-permissions'), 'title' => t('Configure permissions'))),
+      );
+    }
+    // Generate link for module's configuration page, if the module provides
+    // one.
+    if ($module->status && isset($module->info['configure'])) {
+      $configure_link = menu_get_item($module->info['configure']);
+      if ($configure_link['access']) {
+        $extra['links']['configure'] = array(
+          '#type' => 'link',
+          '#title' => t('Configure'),
+          '#href' => $configure_link['href'],
+          '#options' => array('attributes' => array('class' => array('module-link', 'module-link-configure'), 'title' => $configure_link['description'])),
+        );
+      }
+    }
+
+    // If this module is required by other modules, list those, and then make it
+    // impossible to disable this one.
+    foreach ($module->required_by as $required_by => $v) {
+      // Hidden modules are unset already.
+      if (isset($visible_files[$required_by])) {
+        if ($files[$required_by]->status == 1 && $module->status == 1) {
+          $extra['required_by'][] = t('@module (<span class="admin-enabled">enabled</span>)', array('@module' => $files[$required_by]->info['name']));
+          $extra['disabled'] = TRUE;
+        }
+        else {
+          $extra['required_by'][] = t('@module (<span class="admin-disabled">disabled</span>)', array('@module' => $files[$required_by]->info['name']));
+        }
+      }
+    }
+    // Find the time interval to group this module under.
+    $interval = _system_get_interval($module->info['mtime']);
+    $form['modules'][$interval][$filename] = _system_modules_build_row($module->info, $extra);
+  }
+
+  // Fieldset by 'today', 'yesterday', 'this week', ...
+  // Add basic information to the fieldsets.
+  foreach (element_children($form['modules']) as $interval) {
+    $form['modules'][$interval] += array(
+      '#type' => 'fieldset',
+      '#title' => t($interval),
+      '#collapsible' => TRUE,
+      '#theme' => 'system_modules_fieldset',
+      '#header' => array(
+        array('data' => t('Enabled'), 'class' => array('checkbox')),
+        t('Name'),
+        t('Version'),
+        t('Description'),
+        array('data' => t('Operations'), 'colspan' => 3),
+      ),
+      // Ensure that the "Core" package fieldset comes first.
+      '#weight' => _system_interval_weight($interval),
+    );
+  }
+
+  $form['actions'] = array('#type' => 'actions');
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save configuration'),
+  );
+  $form['#action'] = url('admin/modules/recent/confirm');
+
+  return $form;
+}
+/**
  * Array sorting callback; sorts modules or themes by their name.
  */
 function system_sort_modules_by_info_name($a, $b) {
@@ -928,6 +1105,13 @@ function system_sort_modules_by_info_name($a, $b) {
 /**
  * Array sorting callback; sorts modules or themes by their name.
  */
+function system_sort_modules_by_info_mtime($a, $b) {
+  return strcasecmp($a->info['mtime'], $b->info['mtime']);
+}
+
+/**
+ * Array sorting callback; sorts modules or themes by their name.
+ */
 function system_sort_themes($a, $b) {
   if ($a->is_default) {
     return -1;
@@ -939,6 +1123,55 @@ function system_sort_themes($a, $b) {
 }
 
 /**
+ * Return a list of time intervals.
+ *
+ * Glorified define.
+ *
+ * @see: _system_interval_weight()
+ * @see: _system_get_timegroup()
+ */
+function _system_intervals() {
+  // Find the most recent midnight.
+  $today = strtotime(date('Y-m-d 00:00:00'));
+  return array(
+    'Today' => array('timestamp' => $today, 'weight' => -10),
+    'Yesterday' => array( 'timestamp' => ($today - (60 * 60 * 24)), 'weight' => -9),
+    'The past week' => array( 'timestamp' => ($today - (60 * 60 * 24 * 7)), 'weight' => -5),
+    'More than a week ago' => array( 'timestamp' => 0, 'weight' => -1),
+  );
+}
+
+/*
+ * Return the weighting for an interval.
+ *
+ * @see: system_modules_recent()
+ */
+function _system_interval_weight($interval) {
+  $intervals = _system_intervals();
+  foreach ($intervals as $name => $data) {
+    if ($interval == $name) {
+      return $data['weight'];
+    }
+  }
+  return NULL;
+}
+
+/**
+ * Return a time interval designation for a timestamp.
+ *
+ * @see: system_modules_recent()
+ */
+function _system_get_interval($timestamp) {
+  $intervals = _system_intervals();
+  foreach ($intervals as $name => $data) {
+    if ($timestamp >= $data['timestamp']) {
+      return $name;
+    }
+  }
+  return 'Unknown';
+}
+
+/**
  * Build a table row for the system modules page.
  */
 function _system_modules_build_row($info, $extra) {
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 6711471..04087ea 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -1561,10 +1561,16 @@ function system_schema() {
         'type' => 'blob',
         'not null' => FALSE,
       ),
+      'mtime' => array(
+        'description' => "The Unix timestamp when the module info file was last modified.",
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
     ),
     'primary key' => array('filename'),
     'indexes' => array(
-      'system_list' => array('status', 'bootstrap', 'type', 'weight', 'name'),
+      'system_list' => array('status', 'bootstrap', 'type', 'weight', 'name', 'mtime'),
       'type_name' => array('type', 'name'),
     ),
   );
@@ -1642,6 +1648,18 @@ function system_update_8001() {
 }
 
 /**
+ * Add mtime column to the system table.
+ */
+function system_update_8002() {
+  // Add the new field.
+  db_add_field('system', 'mtime', array('description' => "The Unix timestamp when the module info file was last modified.", 'type' => 'int', 'not null' => TRUE, 'default' => 0), NULL);
+
+  // Drop the old index, then re-create it with the new mtime field included.
+  db_drop_index('system', 'system_list');
+  db_add_index('system', 'system_list', array('status', 'bootstrap', 'type', 'weight', 'name', 'mtime'));
+}
+
+/**
  * @} End of "defgroup updates-7.x-to-8.x"
  * The next series of updates should start at 9000.
  */
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index f16b73f..1769510 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -671,6 +671,19 @@ function system_menu() {
     'access arguments' => array('administer modules'),
     'type' => MENU_VISIBLE_IN_BREADCRUMB,
   );
+  $items['admin/modules/recent'] = array(
+    'title' => 'Recently Added',
+    'page arguments' => array('system_modules_recent'),
+    'access arguments' => array('administer modules'),
+    'type' => MENU_LOCAL_TASK,
+    'file' => 'system.admin.inc',
+    'weight' => 20,
+  );
+  $items['admin/modules/recent/confirm'] = array(
+    'title' => 'List',
+    'access arguments' => array('administer modules'),
+    'type' => MENU_VISIBLE_IN_BREADCRUMB,
+  );
   $items['admin/modules/uninstall'] = array(
     'title' => 'Uninstall',
     'page arguments' => array('system_modules_uninstall'),
@@ -2274,7 +2287,7 @@ function system_update_files_database(&$files, $type) {
   }
 
   // All remaining files are not in the system table, so we need to add them.
-  $query = db_insert('system')->fields(array('filename', 'name', 'type', 'owner', 'info'));
+  $query = db_insert('system')->fields(array('filename', 'name', 'type', 'owner', 'info', 'mtime'));
   foreach ($files as &$file) {
     if (isset($file->exists)) {
       unset($file->exists);
@@ -2286,6 +2299,7 @@ function system_update_files_database(&$files, $type) {
         'type' => $type,
         'owner' => isset($file->owner) ? $file->owner : '',
         'info' => serialize($file->info),
+        'mtime' => $file->info['mtime'],
       ));
       $file->type = $type;
       $file->status = 0;
