diff --git a/core/includes/common.inc b/core/includes/common.inc
index c6a29b7..f508ce4 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -6537,6 +6537,9 @@ function drupal_common_theme() {
       'render element' => 'elements',
       'template' => 'region',
     ),
+    'datetime' => array(
+      'variables' => array('timestamp' => NULL, 'text' => NULL, 'attributes' => array(), 'html' => FALSE),
+    ),
     'status_messages' => array(
       'variables' => array('display' => NULL),
     ),
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 902907a..96718d3 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1463,6 +1463,66 @@ function theme_disable($theme_list) {
  */
 
 /**
+ * Preprocess variables for theme_datetime().
+ */
+function template_preprocess_datetime(&$variables) {
+  // Use the datetime attribute if provided.
+  if (empty($variables['attributes']['datetime'])) {
+    // If the datetime attribute was not provided, attempt to use the timestamp
+    // value as the datetime attribute.
+    if (!empty($variables['timestamp'])) {
+      // Format the datetime attribute.
+      // See http://www.w3.org/TR/html5-author/the-time-element.html#attr-time-datetime
+      $variables['attributes']['datetime'] = format_html_datetime($variables['timestamp']);
+      // If no text for the <time> element was provided, print a human-readable
+      // version of the timestamp.
+      if (!isset($variables['text'])) {
+        $variables['text'] = format_date($variables['timestamp']);
+      }
+    }
+  }
+  // If no text was provided, use the datetime attribute as the text. If the
+  // the datetime attribute is not set then return an empty string.
+  if (!isset($variables['text'])) {
+    $variables['text'] = !empty($variables['attributes']['datetime']) ? check_plain($variables['attributes']['datetime']) : '';
+  }
+}
+
+/**
+ * Returns HTML for a date / time.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - timestamp: (optional) A UNIX timestamp for the datetime. If the
+ *     datetime cannot be represented as a UNIX timestamp, use a valid datetime
+ *     attribute value in $variables['options']['attributes']['datetime'].
+ *   - text: (optional) The content to display in the <time> element. Set
+ *     $variables['options']['html'] to TRUE if this value should be output
+ *     without any HTML filtering. Defaults to a human-readable version of the
+ *     timestamp value or the datetime attribute value.
+ *   - options: (optional) An associative array of additional options, with the
+ *     following elements:
+ *     - 'attributes': An associative array of HTML attributes to apply to the
+ *        time tag. If a datetime attribute is passed in, it will override the
+ *        timestamp. To create a valid datetime attribute value from a UNIX
+ *        timestamp, use format_html_datetime().
+ *        See http://www.w3.org/TR/html5-author/the-time-element.html#attr-time-datetime
+ *     - 'html' (default FALSE): Whether $text is HTML or just plain-text. For
+ *        example, to use a span tag within the time element, this must be set
+ *        to TRUE, or the span tag will be stripped. $text is not sanitized if
+ *        'html' is TRUE. The calling function must ensure that $text is
+ *        already safe.
+ *
+ * @see template_preprocess_datetime
+ */
+function theme_datetime($variables) {
+  $output = '<time' . drupal_attributes($variables['options']['attributes']) . '>';
+  $output .= $variables['options']['html'] ? $variables['text'] : check_plain($variables['text']);
+  $output .= '</time>';
+  return $output;
+}
+
+/**
  * Returns HTML for status and/or error messages, grouped by type.
  *
  * An invisible heading identifies the messages for assistive technology.
diff --git a/core/modules/simpletest/tests/theme.test b/core/modules/simpletest/tests/theme.test
index 7968cf7..5348681 100644
--- a/core/modules/simpletest/tests/theme.test
+++ b/core/modules/simpletest/tests/theme.test
@@ -488,3 +488,55 @@ class ThemeHtmlTplPhpAttributesTestCase extends DrupalWebTestCase {
     $this->assertTrue(count($attributes) == 1, t('Attribute set in the body element via hook_preprocess_html() found.'));
   }
 }
+
+/**
+ * Tests for theme_datetime().
+ */
+class ThemeDatetime extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Theme Datetime',
+      'description' => 'Test the theme_datetime() function.',
+      'group' => 'Theme',
+    );
+  }
+
+  /**
+   * Test function theme_datetime().
+   */
+  function testThemeDatetime() {
+    // Create timestamp and formatted date for testing.
+    $timestamp = 280281600;
+    $date = format_date($timestamp);
+
+    // Test with timestamp.
+    $variables = array(
+      'timestamp' => $timestamp,
+    );
+    $this->assertEqual('<time datetime="1978-11-19T00:00:00Z">' . $date . '</time>', theme('datetime', $variables), t('Test theme_datetime with timestamp.'));
+
+    // Test with text and timestamp.
+    $variables = array(
+      'timestamp' => $timestamp,
+      'text' => 'Dries\'s birthday',
+    );
+    $this->assertEqual('<time datetime="1978-11-19T00:00:00Z">Dries&#039;s birthday</time>', theme('datetime', $variables), t('Test theme_datetime with text and timestamp.'));
+
+    // Test with datetime attribute.
+    $variables = array(
+      'attributes' => array(
+        'datetime' => '1978-11-19',
+      ),
+    );
+    $this->assertEqual('<time datetime="1978-11-19">1978-11-19</time>', theme('datetime', $variables), t('Test theme_datetime with datetime attribute.'));
+
+    // Test with text and datetime attribute.
+    $variables = array(
+      'attributes' => array(
+        'datetime' => '1978-11-19',
+      ),
+      'text' => 'Dries\'s birthday',
+    );
+    $this->assertEqual('<time datetime="1978-11-19">Dries&#039;s birthday</time>', theme('datetime', $variables), t('Test theme_datetime with text and datetime attribute.'));
+  }
+}
