Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.666
diff -u -p -r1.666 common.inc
--- includes/common.inc	28 Jun 2007 07:48:40 -0000	1.666
+++ includes/common.inc	28 Jun 2007 23:45:00 -0000
@@ -1071,31 +1071,27 @@ function format_interval($timestamp, $gr
  * @param $type
  *   The format to use. Can be "small", "medium" or "large" for the preconfigured
  *   date formats. If "custom" is specified, then $format is required as well.
- * @param $format
- *   A PHP date format string as required by date(). A backslash should be used
- *   before a character to avoid interpreting the character as part of a date
- *   format.
- * @param $timezone
- *   Time zone offset in seconds; if omitted, the user's time zone is used.
- * @param $langcode
- *   Optional language code to translate to a language other than
- *   what is used to display the page.
+ * @param $params
+ *   An optional array of extra parameters:
+ *     'langcode'
+ *       Optional language code to translate to a language other than
+ *       what is used to display the page.
+ *     'format'
+ *       A PHP date format string as required by date(). A backslash 
+ *       should be used before a character to avoid interpreting the 
+ *       character as part of a date format.
+ *     'timezone'
+ *       One of the PHP timezone names as returned by 
+ *       timezone_identifiers_list(); if omitted, the user's timezone is 
+ *       used.  This parameter is used only on PHP version > 5.1.
+ *     'offset'
+ *       Time zone offset in seconds; if omitted, the user's offset is 
+ *       used.  This parameter is used only on PHP version < 5.2.
  * @return
  *   A translated date string in the requested format.
  */
-function format_date($timestamp, $type = 'medium', $format = '', $timezone = NULL, $langcode = NULL) {
-  if (!isset($timezone)) {
-    global $user;
-    if (variable_get('configurable_timezones', 1) && $user->uid && strlen($user->timezone)) {
-      $timezone = $user->timezone;
-    }
-    else {
-      $timezone = variable_get('date_default_timezone', 0);
-    }
-  }
-
-  $timestamp += $timezone;
-
+function format_date($timestamp, $type = 'medium', $params = array()) {
+  $langcode = isset($params['langcode']) ? $params['langcode'] : NULL;
   switch ($type) {
     case 'small':
       $format = variable_get('date_format_short', 'm/d/Y - H:i');
@@ -1104,40 +1100,88 @@ function format_date($timestamp, $type =
       $format = variable_get('date_format_long', 'l, F j, Y - H:i');
       break;
     case 'custom':
-      // No change to format
+      $format = $params['format'];
       break;
     case 'medium':
     default:
       $format = variable_get('date_format_medium', 'D, m/d/Y - H:i');
   }
-
   $max = strlen($format);
   $date = '';
-  for ($i = 0; $i < $max; $i++) {
-    $c = $format[$i];
-    if (strpos('AaDFlM', $c) !== FALSE) {
-      $date .= t(gmdate($c, $timestamp), array(), $langcode);
-    }
-    else if (strpos('BdgGhHiIjLmnsStTUwWYyz', $c) !== FALSE) {
-      $date .= gmdate($c, $timestamp);
-    }
-    else if ($c == 'r') {
-      $date .= format_date($timestamp - $timezone, 'custom', 'D, d M Y H:i:s O', $timezone, $langcode);
+  if (date_handle_timezones()) {
+    // Using PHP 5 timezone and date functions.
+    if (isset($params['timezone'])) {
+      $timezone = $params['timezone'];
     }
-    else if ($c == 'O') {
-      $date .= sprintf('%s%02d%02d', ($timezone < 0 ? '-' : '+'), abs($timezone / 3600), abs($timezone % 3600) / 60);
+    else {
+      global $user;
+      if (variable_get('configurable_timezones', 1) && $user->uid && strlen($user->timezone)) {
+        $timezone = $user->timezone;
+      }
+      else {
+        $timezone = variable_get('date_default_timezone', 'UTC');
+      }
     }
-    else if ($c == 'Z') {
-      $date .= $timezone;
+    $date_time = date_create(gmdate('c', $timestamp));
+    date_timezone_set($date_time, timezone_open($timezone));
+    for ($i = 0; $i < $max; $i++) {
+      $c = $format[$i];
+      // AM/pm, days of the week, months, timezone names, and 
+      // timezone abbreviations can be localized.
+      if (strpos('AaeDFlMT', $c) !== FALSE) {
+        $date .= t(date_format($date_time, $c), array(), $langcode);
+      }
+      else if (strpos('BcdGgHhIijLmNnOoPrSstUuWwYyZz', $c) !== FALSE) {
+        $date .= date_format($date_time, $c);
+      }
+      else if ($c == '\\') {
+        $date .= $format[++$i];
+      }
+      else {
+        $date .= $c;
+      }
     }
-    else if ($c == '\\') {
-      $date .= $format[++$i];
+  }
+  else {
+    // Using PHP 4 compatibility mode, with offsets rather than timezones.
+    if (isset($params['offset'])) {
+      $offset = $params['offset'];
     }
     else {
-      $date .= $c;
+      global $user;
+      if (variable_get('configurable_timezones', 1) && $user->uid && strlen($user->offset)) {
+        $offset = $user->offset;
+      }
+      else {
+        $offset = variable_get('date_default_offset', 0);
+      }
+    }
+    $timestamp += $offset;
+    for ($i = 0; $i < $max; $i++) {
+      $c = $format[$i];
+      if (strpos('AaDFlM', $c) !== FALSE) {
+        $date .= t(gmdate($c, $offset), array(), $langcode);
+      }
+      else if (strpos('BdgGhHiIjLmnsStTUwWYyz', $c) !== FALSE) {
+        $date .= gmdate($c, $offset);
+      }
+      else if ($c == 'r') {
+        $date .= format_date($timestamp - $offset, 'custom', array('format' => 'D, d M Y H:i:s O', 'offset' => $offset, 'langcode' => $langcode));
+      }
+      else if ($c == 'O') {
+        $date .= sprintf('%s%02d%02d', ($offset < 0 ? '-' : '+'), abs($offset / 3600), abs($offset % 3600) / 60);
+      }
+      else if ($c == 'Z') {
+        $date .= $offset;
+      }
+      else if ($c == '\\') {
+        $date .= $format[++$i];
+      }
+      else {
+        $date .= $c;
+      }
     }
   }
-
   return $date;
 }
 
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.208
diff -u -p -r1.208 form.inc
--- includes/form.inc	28 Jun 2007 07:48:40 -0000	1.208
+++ includes/form.inc	28 Jun 2007 23:45:02 -0000
@@ -1261,9 +1261,9 @@ function theme_date($element) {
 function expand_date($element) {
   // Default to current date
   if (empty($element['#value'])) {
-    $element['#value'] = array('day' => format_date(time(), 'custom', 'j'),
-                            'month' => format_date(time(), 'custom', 'n'),
-                            'year' => format_date(time(), 'custom', 'Y'));
+    $element['#value'] = array('day' => format_date(time(), 'custom', array('format' => 'j')),
+                            'month' => format_date(time(), 'custom', array('format' => 'n')),
+                            'year' => format_date(time(), 'custom', array('format' => 'Y')));
   }
 
   $element['#tree'] = TRUE;
@@ -1316,7 +1316,7 @@ function date_validate($form) {
  * Helper function for usage with drupal_map_assoc to display month names.
  */
 function map_month($month) {
-  return format_date(gmmktime(0, 0, 0, $month, 2, 1970), 'custom', 'M', 0);
+  return format_date(gmmktime(0, 0, 0, $month, 2, 1970), 'custom', array('format' => 'M', 'offset' => 0, 'timezone' => 'UTC'));
 }
 
 /**
Index: modules/aggregator/aggregator.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v
retrieving revision 1.345
diff -u -p -r1.345 aggregator.module
--- modules/aggregator/aggregator.module	5 Jun 2007 12:13:21 -0000	1.345
+++ modules/aggregator/aggregator.module	28 Jun 2007 23:45:03 -0000
@@ -1399,7 +1399,7 @@ function theme_aggregator_page_item($ite
     $source_date = t('%ago ago', array('%ago' => format_interval(time() - $item->timestamp)));
   }
   else {
-    $source_date = format_date($item->timestamp, 'custom', variable_get('date_format_medium', 'D, m/d/Y - H:i'));
+    $source_date = format_date($item->timestamp);
   }
 
   $output .= "<div class=\"feed-item\">\n";
Index: modules/blogapi/blogapi.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/blogapi/blogapi.module,v
retrieving revision 1.106
diff -u -p -r1.106 blogapi.module
--- modules/blogapi/blogapi.module	30 Apr 2007 17:03:23 -0000	1.106
+++ modules/blogapi/blogapi.module	28 Jun 2007 23:45:04 -0000
@@ -205,7 +205,7 @@ function blogapi_blogger_new_post($appke
   }
 
   if (user_access('administer nodes') && !isset($edit['date'])) {
-    $edit['date'] = format_date(time(), 'custom', 'Y-m-d H:i:s O');
+    $edit['date'] = format_date(time(), 'custom', array('format' => 'Y-m-d H:i:s O'));
   }
 
   node_invoke_nodeapi($edit, 'blogapi new');
@@ -269,7 +269,7 @@ function blogapi_blogger_edit_post($appk
   }
 
   if (user_access('administer nodes') && !isset($edit['date'])) {
-    $node->date = format_date($node->created, 'custom', 'Y-m-d H:i:s O');
+    $node->date = format_date($node->created, 'custom', array('format' => 'Y-m-d H:i:s O'));
   }
   $node = node_submit($node);
   node_save($node);
@@ -644,7 +644,7 @@ function _blogapi_mt_extra(&$node, $stru
 
   // dateCreated
   if ($struct['dateCreated']) {
-    $node->date = format_date(mktime($struct['dateCreated']->hour, $struct['dateCreated']->minute, $struct['dateCreated']->second, $struct['dateCreated']->month, $struct['dateCreated']->day, $struct['dateCreated']->year), 'custom', 'Y-m-d H:i:s O');
+    $node->date = format_date(mktime($struct['dateCreated']->hour, $struct['dateCreated']->minute, $struct['dateCreated']->second, $struct['dateCreated']->month, $struct['dateCreated']->day, $struct['dateCreated']->year), 'custom', array('format' => 'Y-m-d H:i:s O'));
   }
 
   if ($was_array) {
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.556
diff -u -p -r1.556 comment.module
--- modules/comment/comment.module	24 Jun 2007 10:09:52 -0000	1.556
+++ modules/comment/comment.module	28 Jun 2007 23:45:06 -0000
@@ -1504,7 +1504,7 @@ function comment_form(&$form_state, $edi
         $date = $edit['date'];
       }
       else {
-        $date = format_date($edit['timestamp'], 'custom', 'Y-m-d H:i O');
+        $date = format_date($edit['timestamp'], 'custom', array('format' => 'Y-m-d H:i O'));
       }
 
       $form['admin'] = array(
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.842
diff -u -p -r1.842 node.module
--- modules/node/node.module	28 Jun 2007 07:48:40 -0000	1.842
+++ modules/node/node.module	28 Jun 2007 23:45:08 -0000
@@ -2087,7 +2087,7 @@ function node_object_prepare(&$node) {
     }
 
     if (!isset($node->date)) {
-      $node->date = format_date($node->created, 'custom', 'Y-m-d H:i:s O');
+      $node->date = format_date($node->created, 'custom', array('format' => 'Y-m-d H:i:s O'));
     }
   }
 
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.499
diff -u -p -r1.499 system.module
--- modules/system/system.module	28 Jun 2007 00:48:26 -0000	1.499
+++ modules/system/system.module	28 Jun 2007 23:45:11 -0000
@@ -548,7 +548,7 @@ function _system_zonelist() {
   $zones = array();
   foreach ($zonelist as $offset) {
     $zone = $offset * 3600;
-    $zones[$zone] = format_date($timestamp, 'custom', variable_get('date_format_long', 'l, F j, Y - H:i') .' O', $zone);
+    $zones[$zone] = format_date($timestamp, 'custom', array('format' => variable_get('date_format_long', 'l, F j, Y - H:i') .' O', 'offset' => $zone));
   }
   return $zones;
 }
@@ -843,13 +843,13 @@ if (Drupal.jsEnabled) {
 
   // Date settings: construct choices for user
   foreach ($date_short as $f) {
-    $date_short_choices[$f] = format_date(time(), 'custom', $f);
+    $date_short_choices[$f] = format_date(time(), 'custom', array('format' => $f));
   }
   foreach ($date_medium as $f) {
-    $date_medium_choices[$f] = format_date(time(), 'custom', $f);
+    $date_medium_choices[$f] = format_date(time(), 'custom', array('format' => $f));
   }
   foreach ($date_long as $f) {
-    $date_long_choices[$f] = format_date(time(), 'custom', $f);
+    $date_long_choices[$f] = format_date(time(), 'custom', array('format' => $f));
   }
 
   $date_long_choices['custom'] = $date_medium_choices['custom'] = $date_short_choices['custom'] = t('Custom format');
@@ -908,7 +908,7 @@ if (Drupal.jsEnabled) {
     '#title' => t('Custom short date format'),
     '#attributes' => array('class' => '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(time(), 'custom', $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(time(), 'custom', array('format' => $default_short_custom)))),
   );
 
   $date_format_medium = variable_get('date_format_medium', $date_medium[1]);
@@ -931,7 +931,7 @@ if (Drupal.jsEnabled) {
     '#title' => t('Custom medium date format'),
     '#attributes' => array('class' => '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(time(), 'custom', $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(time(), 'custom', array('format' => $default_medium_custom)))),
   );
 
   $date_format_long = variable_get('date_format_long', $date_long[0]);
@@ -954,7 +954,7 @@ if (Drupal.jsEnabled) {
     '#title' => t('Custom long date format'),
     '#attributes' => array('class' => '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(time(), 'custom', $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(time(), 'custom', array('format' => $default_long_custom)))),
   );
 
   $form = system_settings_form($form);
@@ -980,7 +980,7 @@ function system_date_time_settings_submi
  * Return the date for a given format string via Ajax.
  */
 function system_date_time_lookup() {
-  $result = format_date(time(), 'custom', $_GET['format']);
+  $result = format_date(time(), 'custom', array('format' => $_GET['format']));
   echo drupal_to_js($result);
   exit;
 }
