I have a timestamp datatype in database with format 24-JuL-11 10.45.00.000000000 AM and want to get it converted into unix timestamp, how can I get it?
10 Answers
This question is pretty much the inverse of Convert Unixtime to Datetime SQL (Oracle)
As Justin Cave says:
There are no built-in functions. But it's relatively easy to write one. Since a Unix timestamp is the number of seconds since January 1, 1970
As subtracting one date from another date results in the number of days between them you can do something like:
create or replace function date_to_unix_ts( PDate in date ) return number is
l_unix_ts number;
begin
l_unix_ts := ( PDate - date '1970-01-01' ) * 60 * 60 * 24;
return l_unix_ts;
end;
As its in seconds since 1970 the number of fractional seconds is immaterial. You can still call it with a timestamp data-type though...
SQL> select date_to_unix_ts(systimestamp) from dual;
DATE_TO_UNIX_TS(SYSTIMESTAMP)
-----------------------------
1345801660
In response to your comment, I'm sorry but I don't see that behaviour:
SQL> with the_dates as (
2 select to_date('08-mar-12 01:00:00 am', 'dd-mon-yy hh:mi:ss am') as dt
3 from dual
4 union all
5 select to_date('08-mar-12', 'dd-mon-yy')
6 from dual )
7 select date_to_unix_ts(dt)
8 from the_dates
9 ;
DATE_TO_UNIX_TS(DT)
-------------------
1331168400
1331164800
SQL>
There's 3,600 seconds difference, i.e. 1 hour.

- 51,770
- 36
- 127
- 149
-
The value I am passing to PDate comes from $sql = Select TO_DATE(TO_CHAR(fld_from_date, 'DD-Mon-YY HH:MI:SS AM'), 'DD-Mon-YY HH:MI:SS AM') AS date_for_unix_timestamp) Assuming TO_CHAR(fld_from_date, 'DD-Mon-YY HH:MI:SS AM') in the above query results in '08-Mar-12 01:00:00 AM' , the to_date covesrion of this char comes out to be just '08-Mar-12' , what is the reason HH:MI:SS (01:00:00 AM) is not appearing? – deepti Aug 24 '12 at 12:22
-
1Hi @deepti, there's no need to post another answer. You can always click the edit link on your question and change it there. A comment leaves a notification for me as well. I've updated my answer; the lack of visibility could just be something to do with your client? – Ben Aug 24 '12 at 12:36
-
Studying time and leap seconds I have to say your programmatic solution is correct, but the cited definition of Unix Time is not: Unix Time is not the Number of Seconds since 1.1.1970, but it is "The Number of Days since 1.1.1970 times 60 * 60 * 24 plus the Number of seconds since Midnight today! – Falco Apr 16 '14 at 14:37
-
5The function does not consider your current time zone. Unix timestamp is the number of seconds since January 1, 1970 00:00:00 **UTC**. The result is only correct if your local time zone is UTC. – Wernfried Domscheit Jun 26 '19 at 06:22
I realize an answer has already been accepted, but I think it should be made clear that the function in that answer doesn't consider the passed in date's time zone offset. A proper Unix timestamp should be calculated at GMT (+0). Oracle's to_date
function assumes the passed in date is in the local time zone unless otherwise specified. This problem is exacerbated by the fact that Daylight Saving Time is a real thing. I over came this problem with the following function:
create or replace
function unix_time_from_date
(
in_date in date,
in_src_tz in varchar2 default 'America/New_York'
)
return integer
as
ut integer := 0;
tz varchar2(8) := '';
tz_date timestamp with time zone;
tz_stmt varchar2(255);
begin
/**
* This function is used to convert an Oracle DATE (local timezone) to a Unix timestamp (UTC).
*
* @author James Sumners
* @date 01 February 2012
*
* @param in_date An Oracle DATE to convert. It is assumed that this date will be in the local timezone.
* @param in_src_tz Indicates the time zone of the in_date parameter.
*
* @return integer
*/
-- Get the current timezone abbreviation (stupid DST)
tz_stmt := 'select systimestamp at time zone ''' || in_src_tz || ''' from dual';
execute immediate tz_stmt into tz_date;
select
extract(timezone_abbr from tz_date)
into tz
from dual;
-- Get the Unix timestamp
select
(new_time(in_date, tz, 'GMT') - to_date('01-JAN-1970', 'DD-MM-YYYY')) * (86400)
into ut
from dual;
return ut;
end unix_time_from_date;
I have some companion functions, unix_time
and unix_time_to_date
, available at http://jrfom.com/2012/02/10/oracle-and-unix-timestamps-revisited/. I can't believe Oracle has made it all the way to 11g without implementing these.

- 14,485
- 10
- 59
- 77
-
There is no reason for dynamic SQL and `SELECT ... INTO FROM dual`. [NEW_TIME](https://docs.oracle.com/database/121/SQLRF/functions117.htm#SQLRF00671) supports only a small subset of all time zones, so it may fail. It also fails if the input date is not in the current season, try `unix_time_from_date(SYSDATE + 150)`. – Wernfried Domscheit Jun 26 '19 at 06:09
for date:
FUNCTION date_to_unix (p_date date,in_src_tz in varchar2 default 'Europe/Kiev') return number is
begin
return round((cast((FROM_TZ(CAST(p_date as timestamp), in_src_tz) at time zone 'GMT') as date)-TO_DATE('01.01.1970','dd.mm.yyyy'))*(24*60*60));
end;
for timestamp:
FUNCTION timestamp_to_unix (p_time timestamp,in_src_tz in varchar2 default 'Europe/Kiev') return number is
begin
return round((cast((FROM_TZ(p_time, in_src_tz) at time zone 'GMT') as date)-TO_DATE('01.01.1970','dd.mm.yyyy'))*(24*60*60));
end;

- 1,027
- 11
- 18
-
As I found out - and I think as pointed down below - this function does not work correctly for summertime. Ie. it does not take into account the real offset ie. Summertime (!) at the exact p_time but only the offset at the time the query is run – Paschi Jun 16 '21 at 14:41
I'm using following method, which differs a little from other answers in that it uses sessiontimezone()
function to properly get date
select
(
cast((FROM_TZ(CAST(in_date as timestamp), sessiontimezone) at time zone 'GMT') as date) -- in_date cast do GMT
-
TO_DATE('01.01.1970','dd.mm.yyyy') -- minus unix start date
)
* 86400000 -- times miliseconds in day
from dual;

- 1,397
- 1
- 9
- 8
-
Here as well: the sessiontimezone might be different when the query is run at summertime but the conversion should convert a date in wintertime... see below answers for a better solution. – Paschi Jun 16 '21 at 14:42
This was what I came up with:
select substr(extract(day from (n.origstamp - timestamp '1970-01-01 00:00:00')) * 24 * 60 * 60 +
extract(hour from (n.origstamp - timestamp '1970-01-01 00:00:00')) * 60 * 60 +
extract(minute from (n.origstamp - timestamp '1970-01-01 00:00:00')) * 60 +
trunc(extract(second from (n.origstamp - timestamp '1970-01-01 00:00:00')),0),0,15) TimeStamp
from tablename;
FWIW

- 62,887
- 36
- 269
- 388
SELECT (SYSDATE - TO_DATE('01-01-1970 00:00:00', 'DD-MM-YYYY HH24:MI:SS')) * 24 * 60 * 60 * 1000 FROM DUAL

- 3,642
- 19
- 24
For conversion between Oracle time and Unix times I use these functions.
They consider your current timezone. You should also add DETERMINISTIC
keyword, for example if you like to use such function in a function-based index. Conversion between DATE
and TIMESTAMP
should be done implicitly by Oracle.
FUNCTION Timestamp2UnixTime(theTimestamp IN TIMESTAMP, timezone IN VARCHAR2 DEFAULT SESSIONTIMEZONE) RETURN NUMBER DETERMINISTIC IS
timestampUTC TIMESTAMP;
theInterval INTERVAL DAY(9) TO SECOND;
epoche NUMBER;
BEGIN
timestampUTC := FROM_TZ(theTimestamp, timezone) AT TIME ZONE 'UTC';
theInterval := TO_DSINTERVAL(timestampUTC - TIMESTAMP '1970-01-01 00:00:00');
epoche := EXTRACT(DAY FROM theInterval)*24*60*60
+ EXTRACT(HOUR FROM theInterval)*60*60
+ EXTRACT(MINUTE FROM theInterval)*60
+ EXTRACT(SECOND FROM theInterval);
RETURN ROUND(epoche);
END Timestamp2UnixTime;
FUNCTION UnixTime2Timestamp(UnixTime IN NUMBER) RETURN TIMESTAMP DETERMINISTIC IS
BEGIN
RETURN (TIMESTAMP '1970-01-01 00:00:00 UTC' + UnixTime * INTERVAL '1' SECOND) AT LOCAL;
END UnixTime2Timestamp;

- 54,457
- 9
- 76
- 110
-
-
@GPHemsley, some systems use seconds others use milliseconds. It should be fairly obvious how to change it. – Wernfried Domscheit Jun 25 '19 at 18:06
-
1The standard Unix timestamp is in seconds since the epoch, and the question does not indicate needing any variation from that standard. All other answers to this question use seconds, not milliseconds (which is what I meant to say, rather than microseconds). It may be fairly obvious how to change the answer, but it's not immediately obvious that the answer needs changing to begin with. – GPHemsley Jun 25 '19 at 22:17
I agree to what Wernfried Domscheit and James Sumners explained in their posts as solutions - mainly because of the timezone and summertime/wintertime issue !
One of the functions I prefer shorter and without dynamic SQL:
-- as Date
CAST ( FROM_TZ( TIMESTAMP '1970-01-01 00:00:00' + NUMTODSINTERVAL(input_date , 'SECOND') , 'GMT' ) AT TIME ZONE 'Europe/Berlin' AS DATE )
or
-- as Timestamp
FROM_TZ( to_timestamp(Date '1970-01-01' + input_date / 86400 ), 'GMT' ) AT TIME ZONE 'Europe/Berlin'
As "Time Zone" one needs to put the static string (ie 'Europe/Berlin') and not the dbtimezone or sessiontimezone variable, because this might yield a wrong offset because the execution time can be in Summer while the unix Timestamp could be in winter.

- 143
- 7
All the above do this:-
ORA-01873: the leading precision of the interval is too small
if your dates are TIMESTAMP format.
Here's the correct answer (assuming you're smart enough to have set up your server to use UTC.)
select (cast(sys_extract_utc(current_timestamp) as date) - TO_DATE('1970-01-01 00:00:00','YYYY-MM-DD HH24:MI:SS')) * 86400 as gmt_epoch from dual;

- 4,552
- 14
- 29
- 49
SELECT
to_char(sysdate, 'YYYY/MM/DD HH24:MI:SS') dt,
round((sysdate - to_date('19700101 000000', 'YYYYMMDD HH24MISS'))*86400) as udt
FROM dual;

- 7
- 1
-
4It is always advised to add some explanation to your code, especially why it differs from other answers if there are already plenty of them – Bowdzone Aug 05 '15 at 12:03
-