Index: AbstractJdbc1ResultSet.java =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java,v retrieving revision 1.7 diff -u -b -r1.7 AbstractJdbc1ResultSet.java --- AbstractJdbc1ResultSet.java 2002/10/19 22:10:36 1.7 +++ AbstractJdbc1ResultSet.java 2002/12/23 12:49:34 @@ -844,8 +844,15 @@ * 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. * + * According to the Timestamp documentation, fractional digits are kept + * in the nanos field of Timestamp and not in the milliseconds of Date. + * Thus, parsing for fractional digits is entirely separated from the + * rest. + * + * The method assumes that there are no more than 9 fractional + * digits given. Undefined behavior if this is not the case. + * * @param s The ISO formated date string to parse. * @param resultSet The ResultSet this date is part of. * @@ -881,6 +888,18 @@ rs.sbuf.append(s); int slen = s.length(); + + // + // For a Timestamp, the fractional seconds are stored in the + // nanos field. As a DateFormat is used for parsing which can + // only parse to millisecond precision and which returns a + // Date object, the fractional second parsing is completely + // separate. + // + + int nanos = 0; + + if (slen > 19) { // The len of the ISO string to the second value is 19 chars. If @@ -894,25 +913,42 @@ char c = s.charAt(i++); if (c == '.') { - // Found a fractional value. Append up to 3 digits including - // the leading '.' + // Found a fractional value. + + final int start = i; + do { - if (i < 24) - rs.sbuf.append(c); c = s.charAt(i++); } while (i < slen && Character.isDigit(c)); + + + // + // The range [start, i - 1) contains all fractional digits. + // + + final int end = i - 1; - // 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++) - rs.sbuf.append('0'); + try + { + nanos = Integer.parseInt(s.substring(start, end)); } - else + catch (NumberFormatException e) { - // No fractional seconds, lets add some. - rs.sbuf.append(".000"); + // this Exception can never happen, as the range has + // been checked before. + } + + + // + // The nanos field stores nanoseconds. Adjust the parsed + // value to the correct magnitude. + // + + for (int digitsToNano = 9 - (end - start); + digitsToNano > 0; --digitsToNano) + nanos *= 10; } if (i < slen) @@ -929,7 +965,7 @@ rs.sbuf.append(":00"); // we'll use this dateformat string to parse the result. - df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z"); + df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); } else { @@ -938,11 +974,11 @@ if (pgDataType.equals("timestamptz")) { rs.sbuf.append(" GMT"); - df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z"); + df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); } else { - df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } } } @@ -982,8 +1018,13 @@ // All that's left is to parse the string and return the ts. if ( org.postgresql.Driver.logDebug ) org.postgresql.Driver.debug( "" + df.parse(rs.sbuf.toString()).getTime() ); + + final Timestamp result = + new Timestamp(df.parse(rs.sbuf.toString()).getTime()); + + result.setNanos(nanos); - return new Timestamp(df.parse(rs.sbuf.toString()).getTime()); + return result; } catch (ParseException e) {