Bug 16574 - java.sql.Timestamp#toString() does not deal with fractional seconds correctly
Summary: java.sql.Timestamp#toString() does not deal with fractional seconds correctly
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libgcj (show other bugs)
Version: unknown
: P2 normal
Target Milestone: 4.0.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-07-15 19:02 UTC by Vadim Nasardinov
Modified: 2004-07-15 22:32 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2004-07-15 19:08:19


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Vadim Nasardinov 2004-07-15 19:02:59 UTC
java.util.Timestamp's public constructor Timestamp(long date) fails to
initialize the "nanos" field correctly.  This leads to
Timestamp#toString() producing an incorrectly formatted value.

Even if the "nanos" field *were* initialized by the above constructor
correctly, toString() would still be wrong, because it fails to
left-pad the value of "nanos" with zeros.  For instance, if "nanos" is
1, the returned String is something like
   "2004-11-09 06:33:19.1"

rather than the correct
   "2004-11-09 06:33:19.000000001".

The following test illustrates the problem:

  | $ cat TStampTest.java 
  | import java.sql.Timestamp;
  | 
  | /**
  |  * http://tinyurl.com/67s3k
  |  **/
  | public class TStampTest {
  | 
  |     public final static void main(String[] args) {
  |         Timestamp ts = new Timestamp(1099999999333L);
  |         log(ts, "333 milliseconds:");
  |         ts.setNanos(42);
  |         log(ts, "42 nanoseconds");
  |     }
  | 
  |     private static void log(String msg) {
  |         System.out.println(msg);
  |     }
  |     private static void log(Timestamp ts, String msg) {
  |         log(msg);
  |         log("  ts:            " + ts);
  |         log("  ts.getTime():  " + ts.getTime());
  |         log("  ts.getNanos(): " + ts.getNanos());
  |     }
  | }


With Sun's JDK 1.4, I get:

  | $ java -cp . TStampTest
  | 333 milliseconds:
  |   ts:            2004-11-09 06:33:19.333
  |   ts.getTime():  1099999999333
  |   ts.getNanos(): 333000000
  | 42 nanoseconds
  |   ts:            2004-11-09 06:33:19.000000042
  |   ts.getTime():  1099999999000
  |   ts.getNanos(): 42

(Note that JDK 1.3 yields a different result.  Not shown here.)

With libgcj, I get:

  | $ gij TStampTest
  | 333 milliseconds:
  |   ts:            2004-11-09 06:33:19.0
  |   ts.getTime():  1099999999333
  |   ts.getNanos(): 0
  | 42 nanoseconds
  |   ts:            2004-11-09 06:33:19.42
  |   ts.getTime():  1099999999333
  |   ts.getNanos(): 42


The above is for
http://savannah.gnu.org/cgi-bin/viewcvs/gcc/gcc/libjava/java/sql/Timestamp.java?rev=1.9


As a philosophical aside, part of the problem is that Timestamp is a
mess from the API perspective, and always has been.  Note that Sun's
Javadoc admits the following:

http://java.sun.com/j2se/1.3/docs/api/java/sql/Timestamp.html
http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Timestamp.html

    Due to the differences between the Timestamp class and the
    java.util.Date class mentioned above, it is recommended that code
    not view Timestamp values generically as an instance of
    java.util.Date. The inheritance relationship between Timestamp and
    java.util.Date really denotes implementation inheritance, and not
    type inheritance.
Comment 1 Bryce McKinlay 2004-07-15 19:08:19 UTC
Confirmed.
Comment 2 GCC Commits 2004-07-15 22:15:04 UTC
Subject: Bug 16574

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	bryce@gcc.gnu.org	2004-07-15 22:14:45

Modified files:
	libjava        : ChangeLog 
	libjava/java/sql: Timestamp.java 

Log message:
	2004-07-15  Bryce McKinlay  <mckinlay@redhat.com>
	
	PR libgcj/16574
	* java/sql/Timestamp.java (dateFormat): Renamed from sdf.
	(decimalFormat): New static variable.
	(sbuf): Likewise.
	(getTime): New. Override Date.getTime().
	(toString): Synchronize. Use decimalFormat to format nanos value
	correctly. Truncate extra zeros.
	(before): Compare getNanos() only if getTime() is equal.
	(after): Likewise.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libjava/ChangeLog.diff?cvsroot=gcc&r1=1.2935&r2=1.2936
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libjava/java/sql/Timestamp.java.diff?cvsroot=gcc&r1=1.9&r2=1.10

Comment 3 Bryce McKinlay 2004-07-15 22:32:10 UTC
Fix checked in to HEAD.