I'm struggling from a couple of hours to understand what's going on with the TimeStamp
s in my code.
Both the Oracle DB and the java application are in PDT
Select from DB:
select id, time_stamp from some_Table where id = '3de392d69c69434eb907f1c0d2802bf0';
3de392d69c69434eb907f1c0d2802bf0 09-DEC-2014 12.45.41.354000000 PM
select id, time_stamp at time zone 'UTC' from some_Table where id = '3de392d69c69434eb907f1c0d2802bf0';
3de392d69c69434eb907f1c0d2802bf0 09-DEC-2014 12.45.41.354000000 PM
The field in the Oracle database is TimeStamp
, hence no timezone information is stored.
Timestamp dbTimeStamp = dbRecord.getLastLoginTime();
System.out.println(dbTimeStamp.toString()); // 2014-12-09 12:16:50.365
System.out.println(dbTimeStamp.getTime()); // 1418156210365 --> Tue Dec 09 2014 20:16:50 UTC?
According to the documentation , getTime()
Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Timestamp object.
Why are 8 hours (PDT - UTC)
of extra time added to the response of getTime()
?
TimeStamp.toString()
internally uses Date.getHours()
whose javadoc states:
Returns the hour represented by this Date object. The returned value is a number (0 through 23) representing the hour within the day that contains or begins with the instant in time represented by this Date object, as interpreted in the local time zone.
So toString
is using your local time zone whereas getDate
doesn't.
These two are consistent with each other. The getTime()
method gives you the absolute millicecond value, which you chose to interpret in UTC. The toString()
method gives you that same millisecond value interpreted in the associated timezone. So it is not getTime()
which is adding the time, but toString()
which is subtracting it. This is not really documented, but that is how it behaves.
The most important takeaway should be not to rely on Timestamp.toString
because it is misleading. The whole timezone mechanism within Date
(and Timestamp
is a subclass) has been deprecated a long time ago. Instead use just the getTime()
value and have it formatted by other APIs, such as Java 8 Date/Time API.
Apparently, the toString()
output is actually the correct one, which for me is just one small addition to the thick catalog of all things wrong with Java's date/time handling. You probably receive the timestamp from the database as a formatted string, not the millisecond value. JDBC then parses that into a millisecond value according to the timezone associated with the Timestamp
instance, such that the output of toString()
matches what was returned by the database, and the actual millisecond value being secondary.
Thanks to the answers above and the references on SO. This answer finally helped me in understanding where I was going wrong in understanding TimeStamps.
Qouting from the linked answer
Note: Timestamp.valueOf("2010-10-23 12:05:16"); means "create a timestamp with the given time in the default timezone".
TimeStamp represents an instant of time. By default, that instant of time in the current Timezone.
The timestamps being written to the DB were UTC instants. ie current UTC time was being written. Hence, no matter where the application was deployed, the value being written to the DB was the same TimeStamp.
However, while reading the TimeStamp generated assumes the default TimeZone as read from the deployment JVM. Hence, the value read was the instant in PST timezone. The actual UTC Value being 8 hours more than the PST time. Hence, the difference.
TimeStamp.getTime()
returns milliseconds from UTC. TimeStamp.toString()
returns the representation of time in the current TimeZone
. Thanks @marko-topolnik
To take an example,
2014-12-09 12:16:50.365
2014-12-09 12:16:50.365
in PST 2014-12-09 20:16:50
Hence, the solution was to add the TimeZone
offset to the values read from the database to get the instants as UTC
TimeStamps.
The key here was " TimeStamp is a time instant without TimeZone information. The timestamp is assumed to be relative to the default system TimeZone.
" - It took me a really long while to comprehend this.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.