Обсуждение: Unexpected value in Time object
I had a unit test fail for an ORM I'm writing. I'm creating an object, persisting it in PostgreSQL 8.3 Windows using the postgresql-8.3-603.jdbc3.jar file retrieved from http://repo1.maven.org/maven2/postgresql/postgresql/8.3-603.jdbc3/, retrieving it back and comparing it to the original.
I created a java.sql.Time object with an inner "fastTime" value of 1, storing it in a "time with time zone" field using a PreparedStatement insert. When I retrieve it, also via PreparedStatement, I notice that the "fastTime" value is not the value 1 that I expected, but 86400001 instead. Although the toString() output looks the same for these two values, the check originalObject.equals(retrievedObject) returns false.
The JavaDoc for the java.sql.Time object states, 'The date components should be set to the "zero epoch" value of January 1, 1970 and should not be accessed.', which suggests that the driver's returned value is out of compliance.
Database ENCODING = 'WIN1252'; jdk1.6.0_06. Feel free to contact me for any additional details.
John Pile
Sacramento, CA
John Pile wrote: > I created a java.sql.Time object with an inner "fastTime" value of 1, > storing it in a "time with time zone" field using a PreparedStatement > insert. When I retrieve it, also via PreparedStatement, I notice that > the "fastTime" value is not the value 1 that I expected, but 86400001 > instead. Although the toString() output looks the same for these two > values, the check originalObject.equals(retrievedObject) returns false. What is your JVM's default timezone? What is the actual value stored in the DB? -O
On Tue, 28 Oct 2008, Oliver Jowett wrote: > What is your JVM's default timezone? > What is the actual value stored in the DB? > The attached test case shows the results of trying to store a Time object with one millisecond in a timetz field with a America/Los_Angelese JVM timezone. Orig Time: 16:00:00 Orig TZ offset: 480 Orig millis: 1 Result as String: 16:00:00.001-08 Result Time: 16:00:00 Result TZ Offset: 480 Result millis: 86400001 Kris Jurka
Вложения
Kris Jurka wrote: > > > On Tue, 28 Oct 2008, Oliver Jowett wrote: > >> What is your JVM's default timezone? >> What is the actual value stored in the DB? >> > > The attached test case shows the results of trying to store a Time > object with one millisecond in a timetz field with a > America/Los_Angelese JVM timezone. > > Orig Time: 16:00:00 > Orig TZ offset: 480 > Orig millis: 1 > Result as String: 16:00:00.001-08 > Result Time: 16:00:00 > Result TZ Offset: 480 > Result millis: 86400001 Ok, after looking at this some more, the driver seems to be doing the correct thing. "new Time(1)" is 1 Jan 1970 00:00:00.001 UTC This is equivalent to 31 Dec 1969 16:00:00.001 -0800 So the original Time value is actually the one that is out of spec if your default timezone is -0800, since it has a day/month/year that doesn't match the "zero epoch" requirement of Time. The result returned by the driver is 2 Jan 1970 00:00:00.001 which is equivalent to 1 Jan 1970 16:00:00.001 -0800. This appears to be the correct representation in a -0800 timezone. The driver is actually constructing the returned Time from a Calendar initialized like this (using an -0800 calendar) > cal.set(Calendar.HOUR_OF_DAY, 16); > cal.set(Calendar.MINUTE, 0); > cal.set(Calendar.SECOND, 0); > cal.set(Calendar.MILLISECOND, 1); > cal.set(Calendar.ERA, GregorianCalendar.AD); > cal.set(Calendar.YEAR, 1970); > cal.set(Calendar.MONTH, 0); > cal.set(Calendar.DAY_OF_MONTH, 1); which results in the 86400001ms value you see. java.sql.Time is generally a horrible interface to work with, since it depends so much on the default JVM timezone :( About all you can do with it is work in the default timezone and use getHours/getMinutes/getSeconds/getMilliseconds. The actual milliseconds value used internally to represent a particular time will vary wildly depending on the JVM's timezone. -O