--- includes/common.inc.ORIG	2008-04-07 08:43:55.000000000 +1000
+++ includes/common.inc	2008-04-09 13:26:57.000000000 +1000
@@ -1176,39 +1176,40 @@ function format_date($timestamp, $type =
       $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('AaDlM', $c) !== FALSE) {
-      $date .= t(gmdate($c, $timestamp), array(), $langcode);
-    }
-    else if ($c == 'F') {
-      // Special treatment for long month names: May is both an abbreviation
-      // and a full month name in English, but other languages have
-      // different abbreviations.
-      $date .= trim(t('!long-month-name '. gmdate($c, $timestamp), array('!long-month-name' => ''), $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);
-    }
-    else if ($c == 'O') {
-      $date .= sprintf('%s%02d%02d', ($timezone < 0 ? '-' : '+'), abs($timezone / 3600), abs($timezone % 3600) / 60);
-    }
-    else if ($c == 'Z') {
-      $date .= $timezone;
-    }
-    else if ($c == '\\') {
-      $date .= $format[++$i];
-    }
-    else {
-      $date .= $c;
+  // Replace entries in $format string which need to be translated 
+  // with escaped string '+=X=+', where X is a format specifier which 
+  // requires translation. The 'F' format specifier requires special 
+  // handling because in English (for example) May is both a short and 
+  // long month name. We need to specify for the 'F' format that it is 
+  // the long month name we will be translating.
+  // These patterns specifically exclude any pattern specifier which has 
+  // been prefixed with '\\' (octal 134).
+
+  // Manually set the expansion for 'r' so that the following rules 
+  // will replace the timezone and localisations correctly
+
+  $format = preg_replace('@(?<!\134)r@','D, d M Y H:i:s O',$format);
+
+  $format = preg_replace('@(?<!\134)([AaDlM])@','+=$1=+',$format);
+  $format = preg_replace('@(?<!\134)F@','+=!\l\o\n\g-\m\o\n\t\h-\n\a\m\e F=+',$format);
+  $format = preg_replace('@(?<!\134)O@', sprintf('%s%02d%02d', ($timezone < 0 ? '-' : '+'), abs($timezone / 3600), abs($timezone % 3600) / 60),$format);
+  $format = preg_replace('@(?<!\134)Z@',$timezone,$format);
+
+  // Make a single call to gmdate using our specially formatted string.
+
+  $date = gmdate($format,$timestamp);
+
+  // Now look for anything that we escaped, and translate it.
+
+  if (preg_match_all('@\+=([-! a-zA-Z]*)=\+@',$date,$matches)) {
+    $arr = $matches[1];
+    foreach($arr as $a) {
+      if (substr($a,0,16) == '!long-month-name')
+        $date = str_replace("+=$a=+",trim(t($a,array('!long-month-name' => ''),$langcode)),$date);
+      else
+        $date = str_replace("+=$a=+",t($a,array(),$langcode),$date);
     }
   }
-
   return $date;
 }
 
