Você pode converter seu carimbo de data/hora com fuso horário para UTC e, em seguida, subtrair a época disso:
select timestamp '2018-10-19 09:12:47.0 AMERICA/DENVER'
- timestamp '1970-01-01 00:00:00.0 UTC' as diff
from dual;
que fornece um tipo de dados de intervalo:
DIFF
----------------------
+17823 15:12:47.000000
Você pode então extrair os elementos disso e multiplicar cada elemento por um fator apropriado para convertê-lo em milissegundos (ou seja, para dias, 60*60*24*1000); e, em seguida, adicione-os juntos:
select extract(day from diff) * 86400000
+ extract(hour from diff) * 3600000
+ extract(minute from diff) * 60000
+ extract(second from diff) * 1000 as unixtime
from (
select timestamp '2018-10-19 09:12:47.0 AMERICA/DENVER'
- timestamp '1970-01-01 00:00:00.0 UTC' as diff
from dual
);
UNIXTIME
--------------------
1539961967000
db<>fiddle
Isso também preserva milissegundos, se o carimbo de data/hora inicial os tiver (isso converte de um tempo 'Unix' enquanto os preserva):
select (timestamp '1970-01-01 00:00:00.0 UTC' + (1539961967567 * interval '0.001' second))
at time zone 'America/Denver' as denver_time
from dual;
DENVER_TIME
--------------------------------------------
2018-10-19 09:12:47.567000000 AMERICA/DENVER
então para converter de volta:
select extract(day from diff) * 86400000
+ extract(hour from diff) * 3600000
+ extract(minute from diff) * 60000
+ extract(second from diff) * 1000 as unixtime
from (
select timestamp '2018-10-19 09:12:47.567 AMERICA/DENVER'
- timestamp '1970-01-01 00:00:00.0 UTC' as diff
from dual
);
UNIXTIME
--------------------
1539961967567
db<>fiddle
Se o seu carimbo de data/hora inicial tiver uma precisão maior do que isso, você precisará truncar (ou round/floor/ceil/cast) para evitar um resultado não inteiro; esta versão apenas trunca a parte de milissegundos extraída:
select diff,
extract(day from diff) * 86400000
+ extract(hour from diff) * 3600000
+ extract(minute from diff) * 60000
+ trunc(extract(second from diff) * 1000) as unixtime
from (
select timestamp '2018-10-19 09:12:47.123456789 AMERICA/DENVER'
- timestamp '1970-01-01 00:00:00.0 UTC' as diff
from dual
);
DIFF UNIXTIME
------------------------- --------------------
+17823 15:12:47.123456789 1539961967123
Sem esse truncamento (ou equivalente), você terminaria com
1539961967123.456789
. Eu tinha esquecido a discrepância dos segundos bissextos; se você precisa/quer lidar com isso, veja esta resposta .