diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java
index 7fea1dab6bea3c3d485b324cb4c418753714a937..b20d2f8a880ec4be51f78711aff11ca52c8b3a47 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java
@@ -491,6 +491,14 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
 	/*
 	 * Get the value of a column in the current row as a
 	 * java.sql.Timestamp object
+	 *
+	 * The driver is set to return ISO date formated strings. We modify this 
+    * string from the ISO format to a format that Java can understand. Java
+    * expects timezone info as 'GMT+09:00' where as ISO gives '+09'.
+    * Java also expects fractional seconds to 3 places where postgres
+    * will give, none, 2 or 6 depending on the time and postgres version.
+    * From version 7.2 postgres returns fractional seconds to 6 places.
+    * If available, we drop the last 3 digits.
 	 *
 	 * @param columnIndex the first column is 1, the second is 2...
 	 * @return the column value; null if SQL NULL
@@ -499,102 +507,80 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
 	public Timestamp getTimestamp(int columnIndex) throws SQLException
 	{
 		String s = getString(columnIndex);
+
 		if (s == null)
 			return null;
 
-		boolean subsecond;
-		//if string contains a '.' we have fractional seconds
-		if (s.indexOf('.') == -1)
-		{
-			subsecond = false;
-		}
-		else
-		{
-			subsecond = true;
-		}
+		StringBuffer sbuf = new StringBuffer(s);
+		SimpleDateFormat df = null;
 
-		//here we are modifying the string from ISO format to a format java can understand
-		//java expects timezone info as 'GMT-08:00' instead of '-08' in postgres ISO format
-		//and java expects three digits if fractional seconds are present instead of two for postgres
-		//so this code strips off timezone info and adds on the GMT+/-...
-		//as well as adds a third digit for partial seconds if necessary
-		StringBuffer strBuf = new StringBuffer(s);
-
-		//we are looking to see if the backend has appended on a timezone.
-		//currently postgresql will return +/-HH:MM or +/-HH for timezone offset
-		//(i.e. -06, or +06:30, note the expectation of the leading zero for the
-		//hours, and the use of the : for delimiter between hours and minutes)
-		//if the backend ISO format changes in the future this code will
-		//need to be changed as well
-		char sub = strBuf.charAt(strBuf.length() - 3);
-		if (sub == '+' || sub == '-')
+		if (s.length() > 19)
 		{
-			strBuf.setLength(strBuf.length() - 3);
-			if (subsecond)
-			{
-				strBuf.append('0').append("GMT").append(s.substring(s.length() - 3, s.length())).append(":00");
-			}
-			else
-			{
-				strBuf.append("GMT").append(s.substring(s.length() - 3, s.length())).append(":00");
-			}
-		}
-		else if (sub == ':')
-		{
-			//we may have found timezone info of format +/-HH:MM, or there is no
-			//timezone info at all and this is the : preceding the seconds
-			char sub2 = strBuf.charAt(strBuf.length() - 5);
-			if (sub2 == '+' || sub2 == '-')
+			// The len of the ISO string to the second value is 19 chars. If
+			// greater then 19, there should be tz info and perhaps fractional
+			// second info which we need to change to java to read it.
+
+			// cut the copy to second value "2001-12-07 16:29:22"
+			int i = 19;
+			sbuf.setLength(i);
+
+			char c = s.charAt(i++);
+			if (c == '.')
 			{
-				//we have found timezone info of format +/-HH:MM
-				strBuf.setLength(strBuf.length() - 5);
-				if (subsecond)
-				{
-					strBuf.append('0').append("GMT").append(s.substring(s.length() - 5));
-				}
-				else
+				// Found a fractional value. Append up to 3 digits including
+				// the leading '.'
+				do
 				{
-					strBuf.append("GMT").append(s.substring(s.length() - 5));
-				}
+					if (i < 24)
+						sbuf.append(c);
+					c = s.charAt(i++);
+				} while (Character.isDigit(c));
+
+				// If there wasn't at least 3 digits we should add some zeros
+				// to make up the 3 digits we tell java to expect.
+				for (int j = i; j < 24; j++)
+					sbuf.append('0');
 			}
-			else if (subsecond)
+			else
 			{
-				strBuf.append('0');
+				// No fractional seconds, lets add some.
+				sbuf.append(".000");
 			}
-		}
-		else if (subsecond)
-		{
-			strBuf = strBuf.append('0');
-		}
 
-		s = strBuf.toString();
+			// prepend the GMT part and then add the remaining bit of
+			// the string.
+			sbuf.append(" GMT");
+			sbuf.append(c);
+			sbuf.append(s.substring(i, s.length()));
 
-		SimpleDateFormat df = null;
+			// Lastly, if the tz part doesn't specify the :MM part then
+			// we add ":00" for java.
+			if (s.length() - i < 5)
+				sbuf.append(":00");
 
-		if (s.length() > 23 && subsecond)
-		{
-			df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSzzzzzzzzz");
-		}
-		else if (s.length() > 23 && !subsecond)
-		{
-			df = new SimpleDateFormat("yyyy-MM-dd HH:mm:sszzzzzzzzz");
-		}
-		else if (s.length() > 10 && subsecond)
-		{
-			df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+			// we'll use this dateformat string to parse the result.
+			df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
 		}
-		else if (s.length() > 10 && !subsecond)
+		else if (s.length() == 19)
 		{
+			// No tz or fractional second info. 
+			// I'm not sure if it is
+			// possible to have a string in this format, as pg
+			// should give us tz qualified timestamps back, but it was
+			// in the old code, so I'm handling it for now.
 			df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 		}
 		else
 		{
+			// We must just have a date. This case is
+			// needed if this method is called on a date column
 			df = new SimpleDateFormat("yyyy-MM-dd");
 		}
 
 		try
 		{
-			return new Timestamp(df.parse(s).getTime());
+			// All that's left is to parse the string and return the ts.
+			return new Timestamp(df.parse(sbuf.toString()).getTime());
 		}
 		catch (ParseException e)
 		{
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
index 66e7b4d3fac77dcbaa8413754415a365f12bd6bc..565847db9f16f4ab0c56693d85a6bf4a9e4b7e88 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
@@ -1591,115 +1591,113 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
 		}
 	}
 
-	public static Timestamp toTimestamp(String s, ResultSet resultSet) throws SQLException
+	/**
+	* Parse a string and return a timestamp representing its value.
+	*
+	* The driver is set to return ISO date formated strings. We modify this 
+	* string from the ISO format to a format that Java can understand. Java
+	* expects timezone info as 'GMT+09:00' where as ISO gives '+09'.
+	* Java also expects fractional seconds to 3 places where postgres
+	* will give, none, 2 or 6 depending on the time and postgres version.
+	* From version 7.2 postgres returns fractional seconds to 6 places.
+	* If available, we drop the last 3 digits.
+	*
+	* @param s         The ISO formated date string to parse.
+	* @param resultSet The ResultSet this date is part of.
+	*
+	* @return null if s is null or a timestamp of the parsed string s.
+	*
+	* @throws SQLException if there is a problem parsing s.
+	**/
+	public static Timestamp toTimestamp(String s, ResultSet resultSet)
+	throws SQLException
 	{
 		if (s == null)
 			return null;
 
-		boolean subsecond;
-		//if string contains a '.' we have fractional seconds
-		if (s.indexOf('.') == -1)
-		{
-			subsecond = false;
-		}
-		else
-		{
-			subsecond = true;
-		}
-
-		//here we are modifying the string from ISO format to a format java can understand
-		//java expects timezone info as 'GMT-08:00' instead of '-08' in postgres ISO format
-		//and java expects three digits if fractional seconds are present instead of two for postgres
-		//so this code strips off timezone info and adds on the GMT+/-...
-		//as well as adds a third digit for partial seconds if necessary
+		// We must be synchronized here incase more theads access the ResultSet
+		// bad practice but possible. Anyhow this is to protect sbuf and
+		// SimpleDateFormat objects
 		synchronized (resultSet)
 		{
-			// We must be synchronized here incase more theads access the ResultSet
-			// bad practice but possible. Anyhow this is to protect sbuf and
-			// SimpleDateFormat objects
+			SimpleDateFormat df = null;
 
-			// First time?
+			// If first time, create the buffer, otherwise clear it.
 			if (resultSet.sbuf == null)
 				resultSet.sbuf = new StringBuffer();
+			else
+				resultSet.sbuf.setLength(0);
 
-			resultSet.sbuf.setLength(0);
+			// Copy s into sbuf for parsing.
 			resultSet.sbuf.append(s);
 
-			//we are looking to see if the backend has appended on a timezone.
-			//currently postgresql will return +/-HH:MM or +/-HH for timezone offset
-			//(i.e. -06, or +06:30, note the expectation of the leading zero for the
-			//hours, and the use of the : for delimiter between hours and minutes)
-			//if the backend ISO format changes in the future this code will
-			//need to be changed as well
-			char sub = resultSet.sbuf.charAt(resultSet.sbuf.length() - 3);
-			if (sub == '+' || sub == '-')
+			if (s.length() > 19)
 			{
-				//we have found timezone info of format +/-HH
+				// The len of the ISO string to the second value is 19 chars. If
+				// greater then 19, there should be tz info and perhaps fractional
+				// second info which we need to change to java to read it.
 
-				resultSet.sbuf.setLength(resultSet.sbuf.length() - 3);
-				if (subsecond)
-				{
-					resultSet.sbuf.append('0').append("GMT").append(s.substring(s.length() - 3)).append(":00");
-				}
-				else
-				{
-					resultSet.sbuf.append("GMT").append(s.substring(s.length() - 3)).append(":00");
-				}
-			}
-			else if (sub == ':')
-			{
-				//we may have found timezone info of format +/-HH:MM, or there is no
-				//timezone info at all and this is the : preceding the seconds
-				char sub2 = resultSet.sbuf.charAt(resultSet.sbuf.length() - 5);
-				if (sub2 == '+' || sub2 == '-')
+				// cut the copy to second value "2001-12-07 16:29:22"
+				int i = 19;
+				resultSet.sbuf.setLength(i);
+
+				char c = s.charAt(i++);
+				if (c == '.')
 				{
-					//we have found timezone info of format +/-HH:MM
-					resultSet.sbuf.setLength(resultSet.sbuf.length() - 5);
-					if (subsecond)
-					{
-						resultSet.sbuf.append('0').append("GMT").append(s.substring(s.length() - 5));
-					}
-					else
+					// Found a fractional value. Append up to 3 digits including
+					// the leading '.'
+					do
 					{
-						resultSet.sbuf.append("GMT").append(s.substring(s.length() - 5));
-					}
+						if (i < 24)
+							resultSet.sbuf.append(c);
+						c = s.charAt(i++);
+					} while (Character.isDigit(c));
+
+					// If there wasn't at least 3 digits we should add some zeros
+					// to make up the 3 digits we tell java to expect.
+					for (int j = i; j < 24; j++)
+						resultSet.sbuf.append('0');
 				}
-				else if (subsecond)
+				else
 				{
-					resultSet.sbuf.append('0');
+					// No fractional seconds, lets add some.
+					resultSet.sbuf.append(".000");
 				}
-			}
-			else if (subsecond)
-			{
-				resultSet.sbuf.append('0');
-			}
 
-			// could optimize this a tad to remove too many object creations...
-			SimpleDateFormat df = null;
+				// prepend the GMT part and then add the remaining bit of
+				// the string.
+				resultSet.sbuf.append(" GMT");
+				resultSet.sbuf.append(c);
+				resultSet.sbuf.append(s.substring(i, s.length()));
 
-			if (resultSet.sbuf.length() > 23 && subsecond)
-			{
-				df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSzzzzzzzzz");
-			}
-			else if (resultSet.sbuf.length() > 23 && !subsecond)
-			{
-				df = new SimpleDateFormat("yyyy-MM-dd HH:mm:sszzzzzzzzz");
-			}
-			else if (resultSet.sbuf.length() > 10 && subsecond)
-			{
-				df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+				// Lastly, if the tz part doesn't specify the :MM part then
+				// we add ":00" for java.
+				if (s.length() - i < 5)
+					resultSet.sbuf.append(":00");
+
+				// we'll use this dateformat string to parse the result.
+				df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
 			}
-			else if (resultSet.sbuf.length() > 10 && !subsecond)
+			else if (s.length() == 19)
 			{
+				// No tz or fractional second info. 
+				// I'm not sure if it is
+				// possible to have a string in this format, as pg
+				// should give us tz qualified timestamps back, but it was
+				// in the old code, so I'm handling it for now.
 				df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 			}
 			else
 			{
+				// We must just have a date. This case is 
+				// needed if this method is called on a date
+				// column
 				df = new SimpleDateFormat("yyyy-MM-dd");
 			}
 
 			try
 			{
+				// All that's left is to parse the string and return the ts.
 				return new Timestamp(df.parse(resultSet.sbuf.toString()).getTime());
 			}
 			catch (ParseException e)
@@ -1708,7 +1706,5 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
 			}
 		}
 	}
-
-
 }