Oracle - 将 Unixtime 转换为本地日期时间,包括 DST(夏令时),反之亦然

Oracle - Convert Unixtime to local datetime including DST (Daylight Savings Time) and vice versa

我有一个带有 UnixTimestamps 的 NUMBER field (UTCSTAMP),我想有一个(自定义)函数来轻松 [​​=28=] 本地日期时间(Europe/Amsterdam),包括 DST(夏令时)时间)。 输出应该是这种格式:'yyyy-mm-dd hh24:mi:ss' 例如:unix_ts2date_function(1576666800)

我找到了这篇文章:Convert Unixtime to Datetime SQL (Oracle),但它没有考虑夏令时。

我还想要一个(自定义)函数来轻松地将本地日期时间 (Europe/Amsterdam) 包括 DST(夏令时)转换为 UnixTimestamp 并在 WHERE 子句中使用它。 例如:

SELECT * FROM table
WHERE UTCSTAMP > date2unix_ts_function('2019-05-01') (DST is active)
AND UTCSTAMP < date2unix_ts_function('2020-11-30') (DST not active)

我还找到这篇文章:Convert timestamp datatype into unix timestamp Oracle 但它也没有考虑夏令时。

向纪元 1970-01-01 UTC 添加 utcstamp 秒(作为 TIMESTAMP 数据类型),然后使用 AT TIME ZONE 将其转换为您想要的时区:

Oracle 设置:

CREATE TABLE your_table ( utcstamp ) AS
SELECT 1576666800 FROM DUAL

查询:

SELECT ( TIMESTAMP '1970-01-01 00:00:00 UTC' + utcstamp * INTERVAL '1' SECOND )
         AT TIME ZONE 'Europe/Amsterdam' AS Amsterdam_Time
FROM   your_table

输出:

| AMSTERDAM_TIME                                 |
| :--------------------------------------------- |
| 2019-12-18 12:00:00.000000000 EUROPE/AMSTERDAM |

查询 2:

如果你想要它作为 DATE 那么只需将所有内容包装在 CAST:

SELECT CAST(
         ( TIMESTAMP '1970-01-01 00:00:00 UTC' + utcstamp * INTERVAL '1' SECOND )
           AT TIME ZONE 'Europe/Amsterdam'
         AS DATE
       ) AS Amsterdam_Time
FROM   your_table

输出:

| AMSTERDAM_TIME      |
| :------------------ |
| 2019-12-18 12:00:00 |

db<>fiddle here


CREATE FUNCTION DATE_TO_UTCEPOCHTIME (
  dt IN DATE,
  tz IN VARCHAR2 DEFAULT 'UTC'
) RETURN NUMBER DETERMINISTIC
IS
BEGIN
  RETURN ROUND(
           ( CAST( FROM_TZ( dt, tz ) AT TIME ZONE 'UTC' AS DATE )
             - DATE '1970-01-01' )
           * 24 * 60 * 60
         );
END;
/

CREATE FUNCTION UTCEPOCHTIME_TO_DATE(
  utctime IN NUMBER,
  tz      IN VARCHAR2 DEFAULT 'UTC'
) RETURN DATE DETERMINISTIC
IS
BEGIN
  RETURN ( TIMESTAMP '1970-01-01 00:00:00 UTC' + utctime * INTERVAL '1' SECOND )
           AT TIME ZONE tz;
END;
/

那么你可以这样做:

SELECT utcepochtime_to_date( utcstamp, 'Europe/Amsterdam' )
FROM   your_table;

输出:

| UTCEPOCHTIME_TO_DATE(UTCSTAMP,'EUROPE/AMSTERDAM') |
| :------------------------------------------------ |
| 2019-12-18 12:00:00                               |

SELECT date_to_utcepochtime(
         DATE '2019-12-18' + INTERVAL '12:00:00' HOUR TO SECOND,
         'Europe/Amsterdam'
       ) AS utcepochtime
FROM   DUAL;

输出:

| UTCEPOCHTIME |
| -----------: |
|   1576666800 |

db<>fiddle here

您可以使用以下查询来实现它,我们使用 FROM_TZ 将 UTC 转换为 Europe/Amsterdam 时间:

SQL> SELECT
  2      TO_CHAR(FROM_TZ( CAST( DATE '1970-01-01' + 1576666800/(24*60*60) AS TIMESTAMP ), 'UTC' )
  3             AT TIME ZONE 'Europe/Amsterdam', 'yyyy-mm-dd hh24:mi:ss') as "desired_date"
  4  FROM
  5      DUAL;

desired_date
-------------------
2019-12-18 12:00:00

SQL>

当我们使用时区的长名称时,夏令时会自动处理,在我们的例子中是 'Europe/Amsterdam'

干杯!!