将日期从 UTC 时区转换为 PST 时区(包括 DST 因素)

Convert a date from UTC timezone to PST Time zone (including DST factor)

我想将 UTC 时区的日期转换为 PST 时区。 NEW_TIME 没有考虑 DST(夏令时)因素,所以我尝试使用 CAST 和 TO_TIMESTAMP_TZ 函数,但都给出了不正确的时间(相差大约 5 小时 30 分钟)。不知道为什么。

SELECT TO_CHAR(TO_TIMESTAMP_TZ(max(end_date) AT TIME ZONE 'PST')
      ,'DD-MON-YYYY HH24:MI:SS')
FROM table1
WHERE NAME= 'FIRST';
SELECT TO_CHAR(CAST((max(end_date) AT TIME ZONE 'PST') AS DATE )
      ,'DD-MON-YYYY HH24:MI:SS')
FROM table1
WHERE NAME= 'FIRST';

我也尝试使用 'US/PACIFIC' 而不是 'PST',但它也给出了相同的结果。

max(end_date) 是:2021-03-15 07:17:16(UTC)

查询正在返回(返回的时间不正确):2021 年 3 月 14 日18:47:16

应该的时间(预计正确时间):2021 年 3 月 15 日00:17:16

任何人都可以帮助更正我的查询或任何其他可以将日期从 UTC 转换为 PST 时区的函数(记住 DST 因素)。

你们有 6 个小时的时差,所以我假设你们和 Asia/Dacca 处于同一时区,并且已经使用以下方法设置了我的会话:

ALTER SESSION SET TIME_ZONE='Asia/Dacca';

现在,如果我创建 table1 数据类型 TIMESTAMP WITH TIME ZONE:

CREATE TABLE table1 (
  name     VARCHAR2(20),
  end_date TIMESTAMP WITH TIME ZONE
);

INSERT INTO table1 ( name, end_date ) VALUES ( 'FIRST', TIMESTAMP '2021-03-15 07:17:16 UTC' );

然后你的查询(你不需要在已经是 TIMESTAMP WITH TIME ZONE 列的列上使用 TO_TIMESTAMP_TZ):

SELECT TO_CHAR(
         max(end_date) AT TIME ZONE 'PST',
         'DD-MON-YYYY HH24:MI:SS'
       ) AS pst_end_date
FROM   table1
WHERE  NAME = 'FIRST';

输出:

| PST_END_DATE         |
| :------------------- |
| 15-MAR-2021 00:17:16 |

并且有效!


但是,如果您使用 TIMESTAMP(不带时区)存储 end_date

CREATE TABLE table1 (
  name     VARCHAR2(20),
  end_date TIMESTAMP
);

INSERT INTO table1 ( name, end_date ) VALUES ( 'FIRST', TIMESTAMP '2021-03-15 07:17:16' );

然后:

SELECT TO_CHAR(
         max(end_date) AT TIME ZONE 'PST',
         'DD-MON-YYYY HH24:MI:SS'
       ) AS pst_end_date
FROM   table1
WHERE  NAME = 'FIRST';

输出:

| PST_END_DATE         |
| :------------------- |
| 14-MAR-2021 18:17:16 |

这重复了您的问题。

这是因为数据库不知道数据的时区,并且会隐含地假定它与 database/session 时区相同,我们已将其设置为 Asia/Dacca 和不是 UTC。相反,我们需要明确告诉数据库使用 UTC 时区进行转换:

SELECT TO_CHAR(
         FROM_TZ(max(end_date), 'UTC') AT TIME ZONE 'PST',
         'DD-MON-YYYY HH24:MI:SS'
       ) AS pst_end_date
FROM   table1
WHERE  NAME = 'FIRST';

输出:

| PST_END_DATE         |
| :------------------- |
| 15-MAR-2021 00:17:16 |

如果您的列具有 DATE 数据类型:

CREATE TABLE table1 (
  name     VARCHAR2(20),
  end_date DATE
);

INSERT INTO table1 ( name, end_date ) VALUES ( 'FIRST', TIMESTAMP '2021-03-15 07:17:16' );

然后您可以使用相同的查询并添加 CAST:

SELECT TO_CHAR(
         FROM_TZ(CAST(max(end_date) AS TIMESTAMP), 'UTC') AT TIME ZONE 'PST',
         'DD-MON-YYYY HH24:MI:SS'
       ) AS pst_end_date
FROM   table1
WHERE  NAME = 'FIRST';

db<>fiddle here