Netezza 使用夏令时将 UTC/GMT 转换为中部时间

问题描述

我在 Netezza 数据库中工作,该数据库将时间存储为 GMT(或者我们的数据工程师告诉我)。我需要能够将其转换为中央标准时间 (CST),但要考虑夏令时。我发现我可以使用类似的东西:

SELECT CURRENT_TIMESTAMP,CURRENT_TIMESTAMP AT TIME ZONE 'CST' AT TIME ZONE 'GMT'

但是,当我运行这个 SELECT 时(请记住,今天是 2021 年 3 月 30 日 - CST 应该与 GTM 仅相差 5 小时),我得到了 6 小时的差异......我查了一个参考Netezza 中有哪些时区可用,我看到一个 5 小时的“CDT”,这适用于 5 小时的差异,但这意味着在我的查询中,我需要在每次 DST 切换时更改此设置或执行某种操作详细的 case 语句,以根据一年中的日期/时间知道使用哪个。

是否有一种简单的自动方法可以将 GTM 时间转换为中央标准时间以考虑夏令时?非常感谢!!!

解决方法

这个问题可以解释为两种方式之一。在这两种情况下,解决方案是根据时间戳是否介于 3 月第二个星期日凌晨 2 点和 11 月第一个星期日凌晨 2 点之间(美国中部时区)来确定要转换到的时区

  1. 表中的时间戳,需要根据当前时间(查询运行时)转换为 CSTCDT
    • 这意味着如果相同的查询在 2 月份运行,结果将与 现在运行
    • 也会根据 netezza 系统的时区设置而有所不同

例如

select 
  t as original,-- extract year from current date and 2nd Sunday of March
  -- use last_day to make sure we account for March 1 being a Sunday
  (next_day(next_day(
           last_day((date_part('years',current_date) || '-02-01'):: date),'sun'),'sun')|| ' 02:00:00'):: timestamp as dstart,-- extract year from current date and 1st Sunday of Nov
  -- use last_day to make sure we account for Nov 1 being a Sunday
  (next_day(last_day(
        (date_part('years',current_date) || '-10-01')::date),'sun')|| ' 02:00:00'):: timestamp as dend,case when current_timestamp between dstart 
  and dend then 'CDT' else 'CST' end as tz,t at time zone tz as converted 
from 
  tdata;

会产生

      ORIGINAL       |       DSTART        |        DEND         | TZ  |       CONVERTED
---------------------+---------------------+---------------------+-----+------------------------
 2021-01-01 17:00:00 | 2021-03-14 02:00:00 | 2021-11-07 02:00:00 | CDT | 2021-01-01 12:00:00-05
 2021-04-01 17:00:00 | 2021-03-14 02:00:00 | 2021-11-07 02:00:00 | CDT | 2021-04-01 12:00:00-05
 2020-04-01 17:00:00 | 2021-03-14 02:00:00 | 2021-11-07 02:00:00 | CDT | 2020-04-01 12:00:00-05
 2020-12-01 17:00:00 | 2021-03-14 02:00:00 | 2021-11-07 02:00:00 | CDT | 2020-12-01 12:00:00-05
(4 rows)

  1. 表中的时间戳需要转换为 CSTCDT,具体取决于夏令时在时间戳中定义的相应 year 中的开始/结束时间。
    • 这更具确定性
select 
  t as original,-- extract year from this timestamp and 2nd Sunday of March
  -- use last_day to make sure we account for March 1 being a Sunday
  (next_day(next_day(
           last_day((date_part('years',t) || '-02-01'):: date),-- extract year from this timestamp and 1st Sunday of Nov
  -- use last_day to make sure we account for Nov 1 being a Sunday
  (next_day(last_day((date_part('years',t) || '-10-01')::date),t at time zone tz as converted 
from 
  tdata;

这将产生(tdata 是一个带有 4 个时间戳的示例表)

      ORIGINAL       |       DSTART        |        DEND         | TZ  |       CONVERTED
---------------------+---------------------+---------------------+-----+------------------------
 2021-01-01 17:00:00 | 2021-03-14 02:00:00 | 2021-11-07 02:00:00 | CST | 2021-01-01 11:00:00-06
 2021-04-01 17:00:00 | 2021-03-14 02:00:00 | 2021-11-07 02:00:00 | CDT | 2021-04-01 12:00:00-05
 2020-04-01 17:00:00 | 2020-03-08 02:00:00 | 2020-11-01 02:00:00 | CDT | 2020-04-01 12:00:00-05
 2020-12-01 17:00:00 | 2020-03-08 02:00:00 | 2020-11-01 02:00:00 | CST | 2020-12-01 11:00:00-06
(4 rows)
,
system.admin(admin)=> select '2021-04-07 11:00:00' as gmt,timezone('2021-04-07 11:00:00','GMT','America/New_York') as eastern,'America/Chicago') as central,'America/Los_Angeles') as pacific;
         gmt         |       eastern       |       central       |       pacific
---------------------+---------------------+---------------------+---------------------
 2021-04-07 11:00:00 | 2021-04-07 07:00:00 | 2021-04-07 06:00:00 | 2021-04-07 04:00:00
(1 row)

system.admin(admin)=> select '2021-03-07 11:00:00' as gmt,timezone('2021-03-07 11:00:00','America/Los_Angeles') as pacific;
         gmt         |       eastern       |       central       |       pacific
---------------------+---------------------+---------------------+---------------------
 2021-03-07 11:00:00 | 2021-03-07 06:00:00 | 2021-03-07 05:00:00 | 2021-03-07 03:00:00
(1 row)

如果我们使用如上所示的“美国/芝加哥”而不是 CDT 和 CST,它会处理夏令时。