首页 > 解决方案 > 确定是春天还是秋天,如果夏令时调整时间

问题描述

我有一个这样的查询:

SELECT 
    to_date(to_char((from_tz(to_timestamp(to_char(my_column, 'YYYY-MM-DD HH:MI:SS PM'), 'YYYY-MM-DD HH:MI:SS PM') ,'America/Edmonton')at time zone 'America/Vancouver'),'YYYY-MM-DD'),'YYYY-MM-DD') as Date_Column
FROM 
    my_table

它将 MST 与 PST 之间的时间转换。这在大多数情况下都有效,除非出现夏令时。然后当时钟向前移动一个小时时会发生一种情况,然后由于丢失了一个小时(例如 1:59 到凌晨 3:00),那么我们正试图转换一个虚构的时间。

所以我知道这个问题,并且我知道 Oracle 会因为这个原因抛出这个错误:

ORA-01878: specified field not found in datetime or interval

我已经在互联网上寻找可能的解决方法,但找不到任何可行的方法。我只想修改我的查询,以便它可以知道现在是一年中的什么时间,或者在时间存在时进行对话,或者在时间不存在时以某种方式处理时间。也许在它丢失时添加额外的小时,并在一年中的其他时间删除它。

有人对此有解决方案吗?这是一个不可能的问题吗?

标签: oracletimezonedst

解决方案


而不是您正在使用的所有转换,只需使用AT TIME ZONE. 根据列的数据类型,您可能需要格外小心。该AT TIME ZONE功能将始终考虑夏令时。

  • 如果您的专栏是 a TIMESTAMP WITH TIME ZONE,那将是理想的,因为您可以说AT TIME ZONE 'PST',您将获得 PST 的时间。
  • 如果该列是 datatype TIMESTAMP,当您使用AT TIME ZONE它时,它将从当前会话的时区转换为您指定的任何时间。
  • 如果您的列是 a DATE,则需要TIMESTAMP先将其转换为 a ,然后才能使用该AT TIME ZONE功能。将 转换DATETIMESTAMP将使时区 0:00 偏移,因此请务必考虑到这一点。

另一个方便的技巧是使用AT LOCAL. 这会将时间戳转换为当前会话的时区。如果您的应用程序用户位于多个时区,这可能会很方便。

例子

我在时区 -04:00(美国东海岸),这就是为什么在下面的示例中显示为我的时区。

WITH
    my_table
    AS
        (SELECT TIMESTAMP '2021-01-01 8:00:00 -7:00'     AS ts_with_tz,
                TIMESTAMP '2021-01-01 8:00:00'           AS ts,
                DATE '2021-01-01' + (8 / 24)             AS dt
           FROM DUAL)
SELECT 1     AS example_num,
       t.ts_with_tz,
       t.ts,
       t.dt
  FROM my_table t
UNION ALL
SELECT 2     AS example_num,
       t.ts_with_tz AT TIME ZONE 'PST',
       t.ts AT TIME ZONE 'PST',
       TO_TIMESTAMP (t.dt) AT TIME ZONE 'PST'
  FROM my_table t
ORDER BY 1;

结果

   EXAMPLE_NUM                                             TS_WITH_TZ                                                     TS                                                     DT
______________ ______________________________________________________ ______________________________________________________ ______________________________________________________
             1 01-JAN-21 08.00.00.000000000 AM -07:00                 01-JAN-21 08.00.00.000000000 AM AMERICA/NEW_YORK       01-JAN-21 08.00.00.000000000 AM AMERICA/NEW_YORK
             2 01-JAN-21 07.00.00.000000000 AM AMERICA/LOS_ANGELES    01-JAN-21 05.00.00.000000000 AM AMERICA/LOS_ANGELES    31-DEC-20 09.00.00.000000000 PM AMERICA/LOS_ANGELES

推荐阅读