在 Oracle 中将本地日期时间(带时区)转换为 Unix 时间戳 [英] Convert local datetime (with time zone) to a Unix timestamp in Oracle

查看:182
本文介绍了在 Oracle 中将本地日期时间(带时区)转换为 Unix 时间戳的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前有一个 SQL 查询,它从我们数据库中的 Unix TIMESTAMP 列返回正确的本地 DATETIME.

I currently have a SQL query that returns the correct local DATETIME from a Unix TIMESTAMP column in our DB.

以下是使用 1539961967000 的特定 TIMESTAMP 的示例:

Here is an example using a specific TIMESTAMP of 1539961967000:

SELECT FROM_TZ(CAST(DATE '1970-01-01' + 1539961967000 * (1/24/60/60/1000) AS TIMESTAMP), 'UTC') AT TIME ZONE 'America/Denver' DATETIME
FROM dual;

返回:

DATETIME
19-OCT-18 09.12.47.000000000 AM AMERICA/DENVER

我很难反转此查询以返回以本地 DATETIME 开头的 Unix TIMESTAMP.

I am having a hard time reversing this query to return a Unix TIMESTAMP starting with a local DATETIME.

有没有人遇到过这种情况?

Has anyone ever encountered this before?

推荐答案

主要问题是 Oracle 有两种方法(至少)将秒数转换为每天到秒的间隔 - 使用函数或对区间文字进行简单的算术运算 - 但没有直接的方法来做相反的事情.

The main issue is that Oracle has two ways (at least) to convert a number of seconds to an interval day-to-second - either with a function or with a simple arithmetic operation on an interval literal - but no direct way to do the reverse.

在下面的两个查询中,首先我展示了如何将 UNIX 时间戳(自 Epoch 以来的毫秒数)转换为 Oracle 时间戳,而不会丢失毫秒.(请参阅我在您的问题下的评论,我指出您的方法将丢失毫秒.)然后我将展示如何反转该过程.

In the two queries below, first I show how to convert a UNIX timestamp (in milliseconds since the Epoch) to an Oracle timestamp, without losing milliseconds. (See my comment under your Question, where I point out that your method will lose milliseconds.) Then I show how to reverse the process.

和你一样,我忽略了Unix 时间戳"忽略闰秒导致的UTC 时间戳"和Unix 时间戳"之间的区别.您的企业必须确定这是否重要.

Like you, I ignore the difference between "timestamp at UTC" and "Unix timestamp" caused by "Unix timestamp" ignoring leap seconds. Your business must determine whether that is important.

Unix 时间戳到带时区的 Oracle 时间戳(保留毫秒):

with
  inputs (unix_timestamp) as (
    select 1539961967186 from dual
  )
select from_tz(timestamp '1970-01-01 00:00:00' 
               + interval '1' second * (unix_timestamp/1000), 'UTC')
                   at time zone 'America/Denver' as oracle_ts_with_timezone
from   inputs
;

ORACLE_TS_WITH_TIMEZONE               
--------------------------------------
2018-10-19 09:12:47.186 America/Denver

带时区的 Oracle 时间戳到 Unix 时间戳(保留毫秒):

with
  sample_data (oracle_ts_with_timezone) as (
    select to_timestamp_tz('2018-10-19 09:12:47.186 America/Denver', 
                           'yyyy-mm-dd hh24:mi:ss.ff tzr')           from dual
  )
select ( extract(second from ts) 
         + (trunc(ts, 'mi') - date '1970-01-01') * (24 * 60 * 60)
       ) * 1000 as unix_timestamp
from   ( select cast(oracle_ts_with_timezone at time zone 'UTC' 
                     as timestamp) as ts
         from   sample_data
       )
;

  UNIX_TIMESTAMP
----------------
   1539961967186

这篇关于在 Oracle 中将本地日期时间(带时区)转换为 Unix 时间戳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆