views:

24

answers:

2

I have a database of start and stop times that have previously all had fairly recent data (1960s through present day) which i've been able to store as long integers. This is very simialr to unix timestamps, only with millisecond precision, so a function like java.util.Date.getTime() would be the value of the current time.

This has worked well so far, but we recently got data from the 1860s, and the following code no longer works when values that result in times < 1901 (give or take):

to_timestamp('1-JAN-1970 00:00:00', 'dd-mon-yyyy hh24:mi:ss') + numtodsinterval(int_to_convert/(1000),'SECOND' );

trying this with a value in milliseconds such as -2177452800000 causes some issues, such as returning the date with a timestamp in the year 2038. Is there a way around this issue? All of the documentation i've looked at the documentation and timestamps should be able to handle years all the way back to the -4000 (BC), so i'm suspecting an issue with the numtodsinterval.

Any ideas suggestions would be greatly appreciated.

A: 

How about select to_date('01-JAN-1970','DD-MON-YYYY') + ( -1111111111 / (60 * 60 * 24*1000) ) from dual; That's what I use to convert Java milliseconds to dates.

Paul Tomblin
The 'int_to_convert' is in milliseconds since Jan 1, 1970. dividing by 60*60^24 loses all the precision i need to preserve.int_to_convert is the number in milliseconds stored in my database, and I just want a way to display these long values as timestamps that will also work for pre-1900 values.
Mike
+1  A: 

How about something like this :

select to_timestamp('1-JAN-1970 00:00:00', 'dd-mon-yyyy hh24:mi:ss') +
         numtodsinterval(val /(1000*60*60*24),'DAY' ) +
         numtodsinterval(
           ((val /(1000*60*60*24)) - (trunc(val /(1000*60*60*24))) ) * 60*60*24,'SECOND')
from (select -2177452812340 val from dual);

Separate out the DAY component and add the whole days, then take the remainder and add that at the higher precision

Gary
Thanks for that response! That gives me the correct timestamp information. Still curious as to why the other way didn't work, but thanks again.
Mike
Just to follow up, i was getting some time differences and ended up removing the second numtodsinterval addition which gave me the correct answer:return to_timestamp('1-JAN-1970 00:00:00', 'dd-mon-yyyy hh24:mi:ss') + numtodsinterval(val /(1000*60*60*24),'DAY' );the precision issue in the below answer might have been caused by the "to_date" instead of "to_timestamp".
Mike