Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Konvertieren Sie die lokale Datumszeit (mit Zeitzone) in einen Unix-Zeitstempel in Oracle

Sie können Ihren Zeitstempel mit Zeitzone in UTC umwandeln und dann die Epoche davon abziehen:

select timestamp '2018-10-19 09:12:47.0 AMERICA/DENVER'
  - timestamp '1970-01-01 00:00:00.0 UTC' as diff
from dual;

was Ihnen einen Intervalldatentyp gibt:

DIFF                  
----------------------
+17823 15:12:47.000000

Sie können dann die Elemente daraus extrahieren und jedes Element mit einem geeigneten Faktor multiplizieren, um es in Millisekunden umzuwandeln (dh für Tage 60 * 60 * 24 * 1000); und füge sie dann zusammen:

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

Dies bewahrt auch Millisekunden, wenn der Startzeitstempel sie enthält (dies konvertiert von einer 'Unix'-Zeit, während sie beibehalten wird):

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

dann zurück konvertieren:

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

Wenn Ihr Startzeitstempel eine höhere Genauigkeit als diese hat, müssen Sie abschneiden (oder rund/Boden/Decke/Guß), um zu vermeiden, dass Sie ein nicht ganzzahliges Ergebnis erhalten. diese Version schneidet nur den extrahierten Teil der Millisekunden ab:

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

Ohne diese Kürzung (oder Äquivalent) würden Sie am Ende 1539961967123.456789 erhalten .

Ich hatte die Schaltsekunden-Diskrepanz vergessen; Wenn Sie damit umgehen müssen/möchten, sehen Sie diese Antwort .