diff options
author | Bruce Momjian <bruce@momjian.us> | 2001-01-24 23:41:04 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2001-01-24 23:41:04 +0000 |
commit | 26e566446f966119be748ea8f553fa280fe864cf (patch) | |
tree | 62dc0dc821813e60ab815cd2a3d816dede54c027 /src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java | |
parent | 7b9dc71405931f698d953378676d7c51ab2d9591 (diff) | |
download | postgresql-26e566446f966119be748ea8f553fa280fe864cf.tar.gz |
Attached is a revised patch that removes the static SimpleDateFormat
objects that Thomas pointed out might be a problem.
PPS. I have included and updated the comments from the original patch
request to reflect the changes made in this revised patch.
> Attached is a set of patches for a couple of bugs dealing with
> timestamps in JDBC.
>
> Bug#1) Incorrect timestamp stored in DB if client timezone different
> than DB.
> The buggy implementation of setTimestamp() in PreparedStatement simply
> used the toString() method of the java.sql.Timestamp object to convert
> to a string to send to the database. The format of this is yyyy-MM-dd
> hh:mm:ss.SSS which doesn't include any timezone information. Therefore
> the DB assumes its timezone since none is specified. That is OK if the
> timezone of the client and server are the same, however if they are
> different the wrong timestamp is received by the server. For example if
> the client is running in timezone GMT and wants to send the timestamp
> for noon to a server running in PST (GMT-8 hours), then the server will
> receive 2000-01-12 12:00:00.0 and interprete it as 2000-01-12
> 12:00:00-08 which is 2000-01-12 04:00:00 in GMT. The fix is to send a
> format to the server that includes the timezone offset. For simplicity
> sake the fix uses a SimpleDateFormat object with its timezone set to GMT
> so that '+00' can be used as the timezone for postgresql. This is done
> as SimpleDateFormat doesn't support formating timezones in the way
> postgresql expects.
>
> Bug#2) Incorrect handling of partial seconds in getting timestamps from
> the DB
>
> When the SimpleDateFormat object parses a string with a format like
> yyyy-MM-dd hh:mm:ss.SS it expects the fractional seconds to be three
> decimal places (time precision in java is miliseconds = three decimal
> places). This seems like a bug in java to me, but it is unlikely to be
> fixed anytime soon, so the postgresql code needed modification to
> support the java behaviour. So for example a string of '2000-01-12
> 12:00:00.12-08' coming from the database was being converted to a
> timestamp object with a value of 2000-01-12 12:00:00.012GMT-08:00. The
> fix was to check for a '.' in the string and if one is found append on
> an extra zero to the fractional seconds part.
>
>
> I also did some cleanup in ResultSet.getTimestamp(). This method has
> had multiple patches applied some of which resulted in code that was no
> longer needed. For example the ISO timestamp format that postgresql
> uses specifies the timezone as an offset like '-08'. Code was added at
> one point to convert the postgresql format to the java one which is
> GMT-08:00, however the old code was left around which did nothing. So
> there was code that looked for yyyy-MM-dd hh:mm:sszzzzzzzzz and
> yyyy-MM-dd hh:mm:sszzz. This second format would never be encountered
> because zzz (i.e. -08) would be converted into the former (also note
> that the SimpleDateFormat object treats zzzzzzzzz and zzz the same, the
> number of z's does not matter).
>
>
> There was another problem/fix mentioned on the email lists today by
> mcannon@internet.com which is also fixed by this patch:
>
> Bug#3) Fractional seconds lost when getting timestamp from the DB
> A patch by Jan Thomea handled the case of yyyy-MM-dd hh:mm:sszzzzzzzzz
> but not the fractional seconds version yyyy-MM-dd hh:mm:ss.SSzzzzzzzzz.
> The code is fixed to handle this case as well.
Barry Lind
Diffstat (limited to 'src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java')
-rw-r--r-- | src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java | 62 |
1 files changed, 38 insertions, 24 deletions
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java index 76df78c248..59aef99ad5 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java @@ -468,33 +468,46 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu if(s==null) return null; - // This works, but it's commented out because Michael Stephenson's - // solution is better still: - //SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); -// Modification by Jan Thomae - String sub = s.substring(s.length() - 3, s.length()-2); - if (sub.equals("+") || sub.equals("-")) { - s = s.substring(0, s.length()-3) + "GMT"+ s.substring(s.length()-3, s.length())+":00"; - } -// ------- - // Michael Stephenson's solution: + 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 + StringBuffer strBuf = new StringBuffer(s); + char sub = strBuf.charAt(strBuf.length()-3); + if (sub == '+' || sub == '-') { + strBuf.setLength(strBuf.length()-3); + if (subsecond) { + strBuf = strBuf.append('0').append("GMT").append(s.substring(s.length()-3, s.length())).append(":00"); + } else { + strBuf = strBuf.append("GMT").append(s.substring(s.length()-3, s.length())).append(":00"); + } + } else if (subsecond) { + strBuf = strBuf.append('0'); + } + + s = strBuf.toString(); + SimpleDateFormat df = null; -// Modification by Jan Thomae - if (s.length()>27) { - df = new SimpleDateFormat("yyyy-MM-dd HH:mm:sszzzzzzzzz"); - } else -// ------- - if (s.length()>21 && s.indexOf('.') != -1) { - df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSzzz"); - } else if (s.length()>19 && s.indexOf('.') == -1) { - df = new SimpleDateFormat("yyyy-MM-dd HH:MM:sszzz"); - } else if (s.length()>19 && s.indexOf('.') != -1) { - df = new SimpleDateFormat("yyyy-MM-dd HH:MM:ss.SS"); - } else if (s.length()>10 && s.length()<=18) { - df = new SimpleDateFormat("yyyy-MM-dd HH:MM:ss"); + 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"); + } else if (s.length()>10 && !subsecond) { + df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } else { - df = new SimpleDateFormat("yyyy-MM-dd"); + df = new SimpleDateFormat("yyyy-MM-dd"); } try { @@ -504,6 +517,7 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu } } + /** * A column value can be retrieved as a stream of ASCII characters * and then read in chunks from the stream. This method is |