diff --git a/includes/common.inc b/includes/common.inc
index f1e8cb6..f2bbe24 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -6407,6 +6407,9 @@ function drupal_common_theme() {
       'render element' => 'elements',
       'template' => 'region',
     ),
+    'datetime' => array(
+      'variables' => array('timestamp' => NULL, 'offset' => NULL, 'format_type' => NULL, 'custom' => NULL, 'pubdate' => FALSE, 'attributes' => array(), 'labels' => array(), 'href' => ''),
+    ),
     'status_messages' => array(
       'variables' => array('display' => NULL),
     ),
diff --git a/includes/theme.inc b/includes/theme.inc
index 6c2b640..c7b7206 100644
--- a/includes/theme.inc
+++ b/includes/theme.inc
@@ -1312,6 +1312,90 @@ function theme_disable($theme_list) {
  */
 
 /**
+ * Returns html for a date / time.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - timestamp: The Unix style timestamp to be themed.
+ *   - offset (optional): A Unix style time from or until the timestamp for printing
+ *     the time element text as an interval
+ *   - format_type (optional): The date format type to be used for the displayed date or
+ *     time, e.g. 'short', 'medium'.
+ *   - custom (optional): The custom formatter to be used if 'format_type' is set to
+ *     'custom'.
+ *   - pubdate: (optional) A boolean value for the pubdate attribute, defaults
+ *     to FALSE.
+ *   - labels (optional): An associative array containing the optional properties
+ *     - past: The label for an interval time that occurred in the past
+ *     - future: The label for an interval time that occurs in the future
+ *     - now: The label for an interval time that is the current time
+ *     - granularity: The granularity of the interval time, passed to format_interval()
+ *     - langcode: The langcode of the interval time, passed to format_interval()
+ *   - href (optional): A string that contains a URL or URL fragment to pass to the l()
+ *     function to render the time element text as a link
+ */
+function theme_datetime($variables) {
+  $output = '<time';
+
+  if (!empty($variables['pubdate'])) {
+    $output .= ' pubdate="pubdate"';
+  }
+  // Print the datetime attribute for machines.
+  // @see http://www.php.net/manual/en/function.gmdate.php
+  // We use gmdate() with Z for the UTC value so that the datestamp remains constant 
+  // regardless of the time on the server that requested it.
+  $output .= ' datetime="' . gmdate('Y-m-d\TH:i:s\Z', $variables['timestamp']) . '"';
+  // Print attributes
+  $output .= drupal_attributes($variables['attributes']) . '>';
+  // Print the formatted timestamp for humans
+  $human_readable = '';
+  if (!empty($variables['offset'])) {
+    // Print the human readable label as a time offset
+    // Prepare the interval labels.
+    // @todo Eventually it would be good to see these labels move into configuration like format_type
+    $past_label =   (!empty($variables['labels']['past'])) ? $variables['labels']['past'] : t('ago');
+    $future_label = (!empty($variables['labels']['future'])) ? $variables['labels']['future'] : t('to go');
+    $now_label =    (!empty($variables['labels']['now'])) ? $variables['labels']['now'] : t('just now');
+    $granularity =  (!empty($variables['labels']['granularity'])) ? $variables['labels']['granularity'] : 2;
+    $langcode =     (!empty($variables['labels']['langcode'])) ? $variables['labels']['langcode'] : NULL;
+    // Calculate the time interval
+    $interval = $variables['timestamp'] - $variables['offset'];
+    // Determine if the date is in the past or the future and
+    // adjust the human readable label according to the interval value
+    switch ($interval) {
+      case ($interval > 0) :
+        $human_readable = format_interval(abs($interval), $granularity, $langcode) . ' ' . $future_label;
+        break;
+      case ($interval < 0) :
+        $human_readable = format_interval(abs($interval), $granularity, $langcode). ' ' . $past_label;
+        break;
+      case ($interval === 0) :
+      default :
+        $human_readable = t($now_label);
+        break;
+    }
+  }
+  else {
+    // Print the human readable label as a timestamp
+    if (empty($variables['custom'])) {
+      $variables['custom'] = '';
+    }
+    $human_readable = format_date($variables['timestamp'], $variables['format_type'], $variables['custom']);
+  }
+  // Print the human readable label as a link if an href is provided
+  if (!empty($variables['href'])) {
+    $output .= l($human_readable, $variables['href']);
+  }
+  else {
+    $output .= $human_readable;
+  }
+  // Close the time element
+  $output .= '</time>';
+
+  return $output;
+}
+
+/**
  * Returns HTML for status and/or error messages, grouped by type.
  *
  * An invisible heading identifies the messages for assistive technology.

